package system.servlets;

import system.util.*;
import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.lang.*;
import java.sql.*;


/**
 * This is wr_rw_Server servlet. It serves the requests from rwServer servlet.
 * @author: Nikolai Rangelov
 */
public class wr_rw_Server extends RemoteHttpServlet implements wr_rw_ServerRMI {
	private static LogPrinter wr_rwLog = null;
	private static Connection wr_rwdbConn = null; // Connection to local DB
	private static volatile byte ServletState = Constants.NOT_INITED;
	public static volatile Object SynchroRegistering = null;
	public static volatile Object SynchroReconn = null;
	public static volatile Object SynchroInit = null;
	private static volatile boolean IsReconn = false;
	private static String db_Drivers = null;
	private static String db_host = null;
	private static String db_user = null;
	private static String db_password = null;
	private static String wr_rwLogPath = null;
	private static int ScreenLogLevel = -1;
	private static int FileLogLevel = -1;
	private static volatile byte ServletErrorState = Constants.NO_ERROR;
/**
 * The method destroys wr_rw_Server servlet. It calls the wr_rwServerDeInit() method to deinit the servlet.
 */

public void destroy() {
	wr_rwServerDeInit();
	ServletState = Constants.NOT_INITED;
	ServletErrorState = Constants.NO_ERROR;
	super.destroy();
}
/**
 * Inits the wr_rw_Server servlet and DO NOT call wr_rwServerInit() (method that makes the primary init).
 * <br> Initialisation is done by request from rwServer.
 */

public void init(ServletConfig config) throws ServletException {
	super.init(config);
	//	initRMI();
	SynchroRegistering = null;
	SynchroRegistering = new Object();
	SynchroReconn = null;
	SynchroReconn = new Object();
	SynchroInit = null;
	SynchroInit = new Object();
}
/**
 * This method serves the requests (http values) from rwServer. It also handles
 * <br> other requests but they are explained in the servlet documentation. 
 */

public void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
	res.setContentType("text/html");
	PrintWriter out = res.getWriter();
	String RT = req.getParameter(Constants.cs_ReqType);
	if (RT != null) {
		switch (Byte.valueOf(RT).byteValue()) {
			case (Constants.TASK_INIT_LITTLE) :
				byte PrevState = ServletState;
				if (ServletState != Constants.INITING) {
					ServletState = Constants.INITING;
					String tdb_Drivers = null;
					String tdb_host = null;
					String tdb_user = null;
					String tdb_password = null;
					String twr_rwLogPath = null;
					int tSLL = -1;
					int tFLL = -1;
					try {
						if ((tdb_Drivers = req.getParameter(dbFields.db_Drivers)) == null) {
							out.print(ServletState);
							out.close();
							ServletState = PrevState;
							return;
						}
						if ((tdb_host = req.getParameter(dbFields.db_host)) == null) {
							out.print(ServletState);
							out.close();
							ServletState = PrevState;
							return;
						}
						if ((tdb_user = req.getParameter(dbFields.db_user)) == null) {
							out.print(ServletState);
							out.close();
							ServletState = PrevState;
							return;
						}
						if ((tdb_password = req.getParameter(dbFields.db_password)) == null) {
							out.print(ServletState);
							out.close();
							ServletState = PrevState;
							return;
						}
						if ((twr_rwLogPath = req.getParameter(Constants.wr_rwLogPath)) == null) {
							out.print(ServletState);
							out.close();
							ServletState = PrevState;
							return;
						}
						if ((tSLL = Integer.valueOf(req.getParameter(Constants.ScreenLogLevel)).intValue()) < 0) {
							out.print(ServletState);
							out.close();
							ServletState = PrevState;
							return;
						}
						if ((tFLL = Integer.valueOf(req.getParameter(Constants.FileLogLevel)).intValue()) < 0) {
							out.print(ServletState);
							out.close();
							ServletState = PrevState;
							return;
						}
					} catch (Exception e) {
						out.print(ServletState);
						out.close();
						ServletState = PrevState;
						return;
					}
					try {
						if (wr_rwServerInit(twr_rwLogPath, tSLL, tFLL, tdb_Drivers, tdb_host, tdb_user, tdb_password) != Constants.READY) {
							if (wr_rwLog != null)
								wr_rwLog.log("wr_rw_Server (service) : Error in init process.", LogPrinter.ERROR);
							out.print(ServletState);
							out.close();
							return;
						}
					} catch (Exception e) {
						if (wr_rwLog != null)
							wr_rwLog.log("wr_rw_Server (service) : Exception in init process.", LogPrinter.ERROR);
						out.print(ServletState);
						out.close();
						ServletState = PrevState;
						return;
					}
				} else {
					wr_rwLog.log("wr_rw_Server (service) : Servlet is being inited at the moment by another user.", LogPrinter.INFO);
					wr_rwLog.flush();
				}
				out.print(ServletState);
				out.close();
				if (ServletState == Constants.READY)
					wr_rwLog.log("wr_rw_Server (service) : Servlet is inited and ready to work.", LogPrinter.INFO);
				wr_rwLog.log("wr_rw_Server (service) : ServletState is " + ServletState, LogPrinter.INFO);
				wr_rwLog.flush();
				return;
			case (Constants.TASK_GET_SERVLET_STATE) :
				out.print(ServletState);
				out.close();
				wr_rwLog.log("wr_rw_Server (service) : ServletState is " + ServletState, LogPrinter.INFO);
				wr_rwLog.flush();
				return;
			case (Constants.TASK_GET_SERVLET_ERROR_STATE) :
				out.print(ServletErrorState);
				out.close();
				wr_rwLog.log("wr_rw_Server (service) : ServletErrorState is " + ServletErrorState, LogPrinter.INFO);
				wr_rwLog.flush();
				return;
			case (Constants.TASK_CHANGE_LOG_LEVELS) :
				int LogLevel = -1;
				String Level = null;
				Level = req.getParameter(Constants.FileLogLevel);
				if (Level == null) {
					out.println("A change for File Log Level not requested. It is " + wr_rwLog.getLogLevel() + ". It won't be changed. Query is : " + req.getQueryString());
					wr_rwLog.log("wr_rw_Server (service) : File Log Level not requested. It won't be changed. Query is : " + req.getQueryString(), LogPrinter.INFO);
				} else {
					try {
						LogLevel = Integer.valueOf(Level).intValue();
						if (LogLevel > -1 && LogLevel <= LogPrinter.ALL) {
							wr_rwLog.setLogLevel(LogLevel);
							out.println("File Log Level changed to " + LogLevel + ".");
							wr_rwLog.log("wr_rw_Server (service) : File Log Level changed " + LogLevel + ".", LogPrinter.INFO);
						} else {
							out.println("File Log Level NOT changed becausse it is not valid (" + LogLevel + "). Current File Log Level is : " + wr_rwLog.getLogLevel());
							wr_rwLog.log("wr_rw_Server (service) : Not a valid File Log Level sent (" + LogLevel + ").", LogPrinter.ERROR);
							wr_rwLog.flush();
						}
					} catch (Exception e) {
						out.println("Error in request sequence for File Log Level. Qurey is : " + req.getQueryString() + ". Current File Log Level is : " + wr_rwLog.getLogLevel());
						wr_rwLog.log("wr_rw_Server (service) : Error in request sequence for File Log Level. Qurey is : " + req.getQueryString() + ". Current File Log Level is : " + wr_rwLog.getLogLevel(), LogPrinter.ERROR);
						wr_rwLog.flush();
					}
				}
				out.print("<br>");
				Level = req.getParameter(Constants.ScreenLogLevel);
				if (Level == null) {
					out.println("A change for Screen Log Level not requested. It is " + wr_rwLog.getScreenLogLevel() + ". It won't be changed. Query is : " + req.getQueryString());
					wr_rwLog.log("wr_rw_Server (service) : Screen Log Level not requested. It won't be changed. Query is : " + req.getQueryString(), LogPrinter.INFO);
				} else {
					try {
						LogLevel = Integer.valueOf(Level).intValue();
						if (LogLevel > -1 && LogLevel <= LogPrinter.ALL) {
							wr_rwLog.setScreenLogLevel(LogLevel);
							out.println("Screen Log Level changed to " + LogLevel + ".");
							wr_rwLog.log("wr_rw_Server (service) : Screen Log Level changed " + LogLevel + ".", LogPrinter.INFO);
						} else {
							out.println("Screen Log Level NOT changed becausse it is not valid (" + LogLevel + "). Current Screen Log Level is : " + wr_rwLog.getLogLevel());
							wr_rwLog.log("wr_rw_Server (service) : Not a valid Screen Log Level sent (" + LogLevel + ").", LogPrinter.ERROR);
							wr_rwLog.flush();
						}
					} catch (Exception e) {
						out.println("Error in request sequence for Screen Log Level. Qurey is : " + req.getQueryString() + ". Current File Log Level is : " + wr_rwLog.getScreenLogLevel());
						wr_rwLog.log("wr_rw_Server (service) : Error in request sequence for Screen Log Level. Qurey is : " + req.getQueryString() + ". Current Screen Log Level is : " + wr_rwLog.getScreenLogLevel(), LogPrinter.ERROR);
						wr_rwLog.flush();
					}
				}
				wr_rwLog.flush();
				out.close();
				return;
			case (Constants.TASK_CLOSE_DIRECT) :
				if (!wr_rwServerDeInit())
					wr_rwLog.log("wr_rw_Server (service) : Servlet deinitialisation faild but servlet is deinited (hard way).", LogPrinter.ERROR);
				else
					wr_rwLog.log("wr_rw_Server (service) : Servlet deinited.", LogPrinter.INFO);
				wr_rwLog.flush();
				out.print(ServletState);
				out.close();
				return;
			default :
				out.close();
				wr_rwLog.log("wr_rw_Server (service) : Error in argument ReqType.", LogPrinter.ERROR);
				wr_rwLog.flush();
				return;
		} //switch
	} //if(ReqType);
	long wrKey = Constants.No_Key;
	long rwKey = Constants.No_Key;
	short marketKey = Constants.No_MarketKey;
	int rwCounts = 0;
	try {
		wrKey = Long.valueOf(req.getParameter(Constants.cs_WR_KEY)).longValue();
		rwKey = Long.valueOf(req.getParameter(Constants.cs_RW_KEY)).longValue();
		marketKey = Short.valueOf(req.getParameter(Constants.cs_MARKET_KEY)).shortValue();
		rwCounts = Integer.valueOf(req.getParameter(Constants.cs_RW_COUNTS)).intValue();
	} catch (Exception e) {
		wr_rwLog.log("wr_rw_Server (service) : Error in parameters send from rwServer.", LogPrinter.ERROR);
		wr_rwLog.flush();
		out.close();
		return;
	}
	try {
		wr_rwMethodFlow(wrKey, rwKey, marketKey, rwCounts);
	} catch (Exception e) {
		wr_rwLog.log("wr_rw_Server (service) : wr_rwMethodFlow failed.", LogPrinter.ERROR);
		wr_rwLog.flush();
	}
	out.close();
	return;
}
/**
 * This method checks the tables in 'wr_rw_Relations' DB. If a table is missing then the method creates it.
 * @return boolean 
 *	       <br> true  - if the method succeed
 * 		   <br> false - if the method failed
 */
private boolean wr_rwCheckTable() {
	String SQLStat = null;
	String result_wr_rwTable = null;
	try {
		for (char p = 'a'; p <= 'z'; p++) {
			result_wr_rwTable = "wr_rw_" + p;
			if (!dbFields.TableExists(result_wr_rwTable, wr_rwdbConn)) {
				SQLStat = "CREATE TABLE " + result_wr_rwTable + " (" + dbFields.db_wr_rw_key + " " + dbFields.db_type_wr_rw_key + "," + dbFields.db_wrKey + " " + dbFields.db_type_wrKey + "," + dbFields.db_rwKey + " " + dbFields.db_type_rwKey + "," + dbFields.db_marketKey + " " + dbFields.db_type_marketKey + "," + dbFields.db_wr_rwCounts + " " + dbFields.db_type_wr_rwCounts + "," + dbFields.db_wr_rwLastCount + " " + dbFields.db_type_wr_rwLastCount + ")";
				if (!dbFields.CreateTable(SQLStat, wr_rwdbConn)) {
					wr_rwLog.log("wr_rw_Server (wr_rwCheckTable) : Error in creating " + result_wr_rwTable + " table for " + dbFields.db_wr_rw_ServerDB, LogPrinter.ERROR);
					wr_rwLog.flush();
					return false;
				}
			}
		} //for
		result_wr_rwTable = "wr_rw_" + Constants.cs_EndNumberTable;
		if (!dbFields.TableExists(result_wr_rwTable, wr_rwdbConn)) {
			SQLStat = "CREATE TABLE " + result_wr_rwTable + " (" + dbFields.db_wr_rw_key + " " + dbFields.db_type_wr_rw_key + "," + dbFields.db_wrKey + " " + dbFields.db_type_wrKey + "," + dbFields.db_rwKey + " " + dbFields.db_type_rwKey + "," + dbFields.db_marketKey + " " + dbFields.db_type_marketKey + "," + dbFields.db_wr_rwCounts + " " + dbFields.db_type_wr_rwCounts + "," + dbFields.db_wr_rwLastCount + " " + dbFields.db_type_wr_rwLastCount + ")";
			if (!dbFields.CreateTable(SQLStat, wr_rwdbConn)) {
				wr_rwLog.log("wr_rw_Server (wr_rwCheckTable) : Error in creating " + result_wr_rwTable + " table for " + dbFields.db_wr_rw_ServerDB, LogPrinter.ERROR);
				wr_rwLog.flush();
				return false;
			}
		}
		result_wr_rwTable = "wr_rw_" + Constants.cs_EndSpecialTable;
		if (!dbFields.TableExists(result_wr_rwTable, wr_rwdbConn)) {
			SQLStat = "CREATE TABLE " + result_wr_rwTable + " (" + dbFields.db_wr_rw_key + " " + dbFields.db_type_wr_rw_key + "," + dbFields.db_wrKey + " " + dbFields.db_type_wrKey + "," + dbFields.db_rwKey + " " + dbFields.db_type_rwKey + "," + dbFields.db_marketKey + " " + dbFields.db_type_marketKey + "," + dbFields.db_wr_rwCounts + " " + dbFields.db_type_wr_rwCounts + "," + dbFields.db_wr_rwLastCount + " " + dbFields.db_type_wr_rwLastCount + ")";
			if (!dbFields.CreateTable(SQLStat, wr_rwdbConn)) {
				wr_rwLog.log("wr_rw_Server (wr_rwCheckTable) : Error in creating " + result_wr_rwTable + " table for " + dbFields.db_wr_rw_ServerDB, LogPrinter.ERROR);
				wr_rwLog.flush();
				return false;
			}
		}
		result_wr_rwTable = null;
		SQLStat = null;
		wr_rwLog.log("wr_rw_Server (wr_rwCheckTable) : Tables checked.", LogPrinter.INFO);
		wr_rwLog.flush();
		return true;
	} catch (SQLException e) {
		if (wr_rwdbReconnect()) {
			wr_rwLog.log("wr_rw_Server (wr_rwCheckTable) : db Reconnected.", LogPrinter.INFO);
			wr_rwLog.flush();
			return wr_rwCheckTable();
		} else {
			wr_rwLog.log("wr_src_Server (wr_rwCheckTable) : SQL Statement error - " + SQLStat + " Exception : " + e, LogPrinter.ERROR);
			wr_rwLog.flush();
			return false;
		}
	} catch (Exception e2) {
		wr_rwLog.log("wr_rw_Server (wr_rwCheckTable) : Exception - " + e2, LogPrinter.ERROR);
		wr_rwLog.flush();
		return false;
	}
}
/**
 * This method connects the wr_rw_Server servlet to 'wr_rw_Relations' DB
 * @return boolean 
 *	       <br> true  - if the method succeed (we have connections)
 * 		   <br> false - if the method failed (we don't have connections)
 */

private boolean wr_rwdbConnect() {
	try {
		Class.forName(db_Drivers).newInstance();
		wr_rwLog.log("wr_rw_Server (wr_rwdbConnect) : Got a driver to " + dbFields.db_wr_rw_ServerDB + " db.", LogPrinter.INFO);
	} catch (Exception E) {
		wr_rwLog.log("wr_rw_Server (wr_rwdbConnect) : Unable to load driver to " + dbFields.db_wr_rw_ServerDB + " db. \n" + E, LogPrinter.ERROR);
		wr_rwLog.flush();
		return false;
	}
	wr_rwdbConn = null;
	try {
		wr_rwdbConn = DriverManager.getConnection(db_host + dbFields.db_wr_rw_ServerDB, db_user, db_password);
		wr_rwLog.log("wr_rw_Server (wr_rwdbConnect) : Conection to " + dbFields.db_wr_rw_ServerDB + " db Established.", LogPrinter.INFO);
		if (wr_rwdbConn == null || wr_rwdbConn.isClosed()) {
			wr_rwLog.flush();
			return false;
		}
		wr_rwLog.flush();
		return true;
	} catch (SQLException E) {
		wr_rwLog.log("wr_rw_Server (wr_rwdbConnect) : SQLException : " + E.getMessage(), LogPrinter.ERROR);
		wr_rwLog.log("wr_rw_Server (wr_rwdbConnect) : SQLState     : " + E.getSQLState(), LogPrinter.ERROR);
		wr_rwLog.log("wr_rw_Server (wr_rwdbConnect) : VendorError  : " + E.getErrorCode(), LogPrinter.ERROR);
		wr_rwLog.flush();
		return false;
	}
}
/**
 * This method disconnects the wr_rw_Server servlet from 'wr_rw_Relations' DB softly. If there is error
 * <br>during disconneting procedure the connection is stoped in hard way (equals null).
 */
 
private void wr_rwdbDisConnect() {
	try {
		if (wr_rwdbConn != null) {
			wr_rwdbConn.close();
			wr_rwLog.log("wr_rw_Server (wr_rwdbConnect) : " + dbFields.db_wr_rw_ServerDB + " db closed.", LogPrinter.INFO);
			wr_rwLog.flush();
			wr_rwdbConn = null;
		}
	} catch (Exception e) {
		wr_rwLog.log("wr_rw_Server (wr_rwdbConnect) : Cannot close the " + dbFields.db_wr_rw_ServerDB + " db \n" + e, LogPrinter.ERROR);
		wr_rwLog.flush();
		return;
	}
	return;
}
/**
 * Reconnects market_rwdbConn to Market_rw DB if servlet had lost its connection.
 * @return boolean
 *	       <br> true  - if the method succeed
 * 		   <br> false - if the method failed
 */
private boolean wr_rwdbReconnect() {
	try {
		if (wr_rwdbConn == null || wr_rwdbConn.isClosed()) {		
			ServletState = Constants.CONN_ERROR;
			ServletErrorState = Constants.CONN_ERROR;
			synchronized (SynchroReconn) {
				if (ServletState == Constants.CONN_ERROR) {
					if (!IsReconn) {
						IsReconn = true;
						if (!wr_rwdbConnect()) {
							wr_rwLog.log("wr_rw_Server (wr_rwdbReconnect) : wr_rwdbConnect() failure.", LogPrinter.ERROR);
							IsReconn = false;
							wr_rwLog.flush();
							return false;
						}
						IsReconn = false;
						ServletState = Constants.READY;
						ServletErrorState = Constants.NO_ERROR;
						wr_rwLog.log("wr_rwServer (wr_rwdbReconnect) : Reconnection to db done.", LogPrinter.INFO);
						return true;
					} else {
						Thread.sleep(1000);
						if (ServletState == Constants.READY) {
							return true;
						}
					}
				} else
					if (ServletState == Constants.READY) {
						return true;
					}
			}
		} else {
			wr_rwLog.log("wr_rwServer (wr_rwdbReconnect) : Possible SQL Statement error. db is connected." , LogPrinter.ERROR);
			wr_rwLog.flush();
		}
		return false;
	} catch (Exception ex) {
		wr_rwLog.log("wr_rwServer (wr_rwdbReconnect) : Exception in re-connect: " + ex, LogPrinter.ERROR);
		wr_rwLog.flush();
		return false;
	}
}
/**
 * This method calculates the last free wr_rw_Key. It looks for the greatest one in the 'wr_rw_Relations'
 * <br>DB and then calculates the new wr_rw_Key.
 * @return wr_rw_Key long - the new key;
 *	       <br> 0 - if error occures
*/
private long wr_rwGet_wr_rw_key(char p, String TableName) {
	try {
		if (!dbFields.IsEmpty(TableName, wr_rwdbConn)) {
			String SQLStat = "SELECT MAX(" + dbFields.db_wr_rw_key + ") FROM " + TableName;
			long res_rwKey = Constants.No_Key;
			try {
				Statement Stmt = wr_rwdbConn.createStatement();
				ResultSet RS = Stmt.executeQuery(SQLStat);
				if (RS.next())
					res_rwKey = RS.getLong(1);
				wr_rwLog.log("wr_rw_Server (wr_rwGet_wr_rw_key) : The Last free key is : " + String.valueOf(res_rwKey), LogPrinter.DEBUG);
				RS.close();
				Stmt.close();
				return (res_rwKey + (1 << 8));
			} catch (SQLException E) {
				if (wr_rwdbReconnect()) {
					wr_rwLog.log("wr_rw_Server (wr_rwGet_wr_rw_key) : db Reconnected.", LogPrinter.INFO);
					wr_rwLog.flush();
					return wr_rwGet_wr_rw_key(p, TableName);
				} else {
					wr_rwLog.log("wr_src_Server (wr_rwGet_wr_rw_key) : SQL Statement error - " + SQLStat + " Exception : " + E, LogPrinter.ERROR);
					wr_rwLog.flush();
					return 0;
				}
			}
		} else {
			if (p >= 'a' && p <= 'z') {
				return ((1 << 8) | p);
			} else {
				if (p >= '0' && p <= '9') {
					return ((1 << 8) | Constants.cc_NumberTableBaseKey);
				} else {
					return ((1 << 8) | Constants.cc_OtherTableBaseKey);
				}
			}
		}
	} catch (SQLException e) {
		if (wr_rwdbReconnect()) {
			wr_rwLog.log("wr_rw_Server (wr_rwGet_wr_rw_key) : db Reconnected.", LogPrinter.INFO);
			wr_rwLog.flush();
			return wr_rwGet_wr_rw_key(p, TableName);
		} else {
			wr_rwLog.log("wr_src_Server (wr_rwGet_wr_rw_key) : SQL Statement error -  Exception : " + e, LogPrinter.ERROR);
			wr_rwLog.flush();
			return 0;
		}
	}
}
/**
 * This method does the job of this servlet. It checks the ServletState and if it is 'READY'
 * <br> continues the procedure.
 * @return boolean 
 *	       <br> true  - if the method succeed 
 * 		   <br> false - if the method failed
 */
public boolean wr_rwMethodFlow(long wrKey, long rwKey, short marketKey, int wr_rw_Counts) {
	do {
		try {
			switch (ServletState) {
				case (Constants.NOT_INITED) :
					if (wr_rwLog != null) {
						wr_rwLog.log("wr_rw_Server (wr_rwMethodFlow) : Servlet in not inited.", LogPrinter.ERROR);
						wr_rwLog.flush();
					}
					return false;
				case (Constants.INITING) :
					Thread.sleep(1000);
					break;
				case (Constants.INIT_ERROR) :
					if (wr_rwLog != null) {
						wr_rwLog.log("wr_rw_Server (wr_rwMethodFlow) : There was error in the init process. Try to reload.", LogPrinter.ERROR);
						wr_rwLog.flush();
					}
					return false;
				case (Constants.READY) :
					break;
				case (Constants.CONN_ERROR) :
					synchronized (SynchroReconn) {
						if (!IsReconn)
							if (ServletState == Constants.CONN_ERROR) {
								IsReconn = true;
								if (!wr_rwdbConnect()) {
									IsReconn = false;
									wr_rwLog.log("wr_rw_Server (wr_rwMethodFlow) : Connection to " + dbFields.db_wr_rw_ServerDB + " cannot be re-established.", LogPrinter.ERROR);
									wr_rwLog.flush();
									return false;
								} else {
									IsReconn = false;
									ServletState = Constants.READY;
									wr_rwLog.log("wr_rw_Server (wr_rwMethodFlow) : Connection to " + dbFields.db_wr_rw_ServerDB + " re-established.", LogPrinter.INFO);
									wr_rwLog.flush();
									break;
								}
							}
					} //synchro
					break;
			} //switch			
		} catch (Exception e) {
			if (wr_rwLog != null) {
				wr_rwLog.log("wr_rw_Server (wr_rwMethodFlow) : There was error in checking ServletState.", LogPrinter.ERROR);
				wr_rwLog.flush();
			}
			return false;
		}
	} while (ServletState != Constants.READY);
	if (wrKey < 1) {
		wr_rwLog.log("wr_rw_Server (wr_rwMethodFlow) : wrKey should be greater than 0 (" + wrKey + ")", LogPrinter.ERROR);
		wr_rwLog.flush();
		return false;
	}
	if (rwKey < 1) {
		wr_rwLog.log("wr_rw_Server (wr_rwMethodFlow) : rwKey should be greater than 0 (" + rwKey + ")", LogPrinter.ERROR);
		wr_rwLog.flush();
		return false;
	}
	if (wr_rw_Counts < 1) {
		wr_rwLog.log("wr_rw_Server (wr_rwMethodFlow) : wr_rw_Counts should be greater than 0 (" + wr_rw_Counts + ")", LogPrinter.ERROR);
		wr_rwLog.flush();
		return false;
	}
	String TableName = null;
	try {
		TableName = wr_rwWhichTable(rwKey);
	} catch (Exception e) {
		wr_rwLog.log("wr_rw_Server (wr_rwMethodFlow) : Error in getting table name for rwKey - " + rwKey, LogPrinter.ERROR);
		wr_rwLog.flush();
	}
	int Update_result = wr_rwUpdateRelation(wrKey, rwKey, wr_rw_Counts, marketKey, TableName);
	switch (Update_result) {
		case (Constants.No_Key) :
			wr_rwLog.log("wr_rw_Server (wr_rwMethodFlow) : Error in wr_rwUpdateRelation() function", LogPrinter.ERROR);
			wr_rwLog.flush();
			return false;
		case (1) :
			wr_rwLog.log("wr_rw_Server (wr_rwMethodFlow) : wrKey = " + wrKey + ", rwKey = " + rwKey + ", marketKey = " + marketKey + " updated in the " + TableName + " table.", LogPrinter.DEBUG);
			return true;
		case (0) :
			if (!wr_rwRegisterRelation(wrKey, rwKey, marketKey, TableName, wr_rw_Counts)) {
				wr_rwLog.log("wr_rw_Server (wr_rwMethodFlow) : wr_rwRegisterRelation() function error. Res from updating = " + Update_result + ". wrKey = " + wrKey + ", rwKey = " + rwKey + ", marketKey = " + marketKey + " is DUBLICATED in " + TableName + " table.", LogPrinter.ERROR);
				wr_rwLog.flush();
				return false;
			}
			return true;
		default :
			if (Update_result > 1) {
				wr_rwLog.log("wr_rw_Server (wr_rwMethodFlow) : Res from updating = " + Update_result + ". wrKey = " + wrKey + ", rwKey = " + rwKey + ", marketKey = " + marketKey + " is DUBLICATED in " + TableName + " table.", LogPrinter.ERROR);
				wr_rwLog.flush();
				return true; /// It should be return false !!!!!!!!!!!!!!!!!
			} else {
				wr_rwLog.log("wr_rw_Server (wr_rwMethodFlow) : Strange error. Res from updating = " + Update_result + ". wrKey = " + wrKey + ", rwKey = " + rwKey + ", marketKey = " + marketKey + " in " + TableName + " table is not updated or inserted.", LogPrinter.ERROR);
				wr_rwLog.flush();
				return false;
			}
	} // switch
}
/**
 * Registers new relation wrKey - rwKey - marketKey.
 * @return boolean 
 *	       <br> true  - if the method succeed (we have connections)
 * 		   <br> false - if the method failed (we don't have connections)
 */
private boolean wr_rwRegisterRelation(long RwrKey, long RrwKey, short RmarketKey, String Rwr_rwTableName, int Rwr_rwCounts) {
	synchronized (SynchroRegistering) {
		int Update_result = wr_rwUpdateRelation(RwrKey, RrwKey, Rwr_rwCounts, RmarketKey, Rwr_rwTableName);
		switch (Update_result) {
			case (Constants.No_Key) :
				wr_rwLog.log("wr_rw_Server (wr_rwRegisterRelation) : Error in wr_rwUpdateRelation() function", LogPrinter.ERROR);
				wr_rwLog.flush();
				return false;
			case (1) :
				wr_rwLog.log("wr_rw_Server (wr_rwRegisterRelation) : wrKey = " + RwrKey + ", rwKey = " + RrwKey + ", marketKey = " + RmarketKey + " updated in the " + Rwr_rwTableName + " table.", LogPrinter.DEBUG);
				return true;
			case (0) :
				break;
			default :
				if (Update_result > 1) {
					wr_rwLog.log("wr_rw_Server (wr_rwRegisterRelation) : Res from updating = " + Update_result + ". wrKey = " + RwrKey + ", rwKey = " + RrwKey + ", marketKey = " + RmarketKey + " is DUBLICATED in " + Rwr_rwTableName + " table.", LogPrinter.ERROR);
					wr_rwLog.flush();
					return true; /// It should be return false !!!!!!!!!!!!!!!!!
				} else {
					wr_rwLog.log("wr_rw_Server (wr_rwRegisterRelation) : Strange error. Res from updating = " + Update_result + ". wrKey = " + RwrKey + ", rwKey = " + RrwKey + ", marketKey = " + RmarketKey + " in " + Rwr_rwTableName + " table is not updated or inserted.", LogPrinter.ERROR);
					wr_rwLog.flush();
					return false;
				}
		} // switch

		long wr_rw_key = wr_rwGet_wr_rw_key(((char) (RrwKey % 256)), Rwr_rwTableName);
		if (wr_rw_key > 1) {
			String SQLStat = "INSERT INTO " + Rwr_rwTableName + " (" + dbFields.db_wr_rw_key + " ," + dbFields.db_wrKey + " ," + dbFields.db_rwKey + "," + dbFields.db_marketKey + "," + dbFields.db_wr_rwCounts + "," + dbFields.db_wr_rwLastCount + ") values (?,?,?,?,?,?)";
			try {
				StringBuffer sql = new StringBuffer(512);
				sql.append(SQLStat);
				PreparedStatement stmt = wr_rwdbConn.prepareStatement(sql.toString());
				stmt.clearParameters();
				stmt.setLong(1, wr_rw_key);
				stmt.setLong(2, RwrKey);
				stmt.setLong(3, RrwKey);
				stmt.setInt(4, RmarketKey);
				stmt.setInt(5, Rwr_rwCounts);
				stmt.setDate(6, new java.sql.Date(System.currentTimeMillis()));
				stmt.executeUpdate();
				wr_rwLog.log("wr_rw_Server (wr_rwRegisterRelation) : RegisterRelation - info inserted.", LogPrinter.DEBUG);
				return true;
			} catch (SQLException e) {
				if (wr_rwdbReconnect()) {
					wr_rwLog.log("wr_rw_Server (wr_rwRegisterRelation) : db Reconnected.", LogPrinter.INFO);
					wr_rwLog.flush();
					return wr_rwRegisterRelation(RwrKey, RrwKey, RmarketKey, Rwr_rwTableName, Rwr_rwCounts);
				} else {
					wr_rwLog.log("wr_src_Server (wr_rwRegisterRelation) : SQL Statement error - " + SQLStat + " Exception : " + e, LogPrinter.ERROR);
					wr_rwLog.flush();
					return false;
				}
			} catch (NumberFormatException e) {
				wr_rwLog.log("wr_rw_Server (wr_rwRegisterRelation) : error format - " + SQLStat + "(" + wr_rw_key + "," + RwrKey + "," + RrwKey + "," + RmarketKey + "," + Rwr_rwCounts + ")", LogPrinter.ERROR);
				wr_rwLog.flush();
				return false;
			}
		} else
			return false;
	} //synchronized		
}
/**
 * Deinits the servlet. Free all resources that the servlet had allocated with wr_rwServerInit() method.
 * @return boolean
 *	       <br> true  - if the method succeed
 * 		   <br> false - if the method failed but deinitin is done in hard way
 */
public boolean wr_rwServerDeInit() {
	try {
		if (wr_rwLog != null) {
			wr_rwLog.log("wr_rw_Server (wr_rwServerDeInit) : ------- Deinitialisation begins ...", LogPrinter.INFO);
		}
		if (wr_rwdbConn != null) {
			wr_rwdbDisConnect();
		}
		wr_rwdbConn = null; // Connection to local DB
		IsReconn = false;
		db_Drivers = null;
		db_host = null;
		db_user = null;
		db_password = null;
		ScreenLogLevel = 0;
		FileLogLevel = 0;
		if (wr_rwLog != null) {
			wr_rwLog.log("wr_rw_Server (wr_rwServerDeInit) : ------- Deinitialisation done. Servlet destroyed.", LogPrinter.INFO);
			wr_rwLog.destroy();
		}
		wr_rwLog = null;
	} catch (Exception e) {
		wr_rwdbConn = null; // Connection to local DB
		IsReconn = false;
		db_Drivers = null;
		db_host = null;
		db_user = null;
		db_password = null;
		ScreenLogLevel = -1;
		FileLogLevel = -1;
		wr_rwLog = null;
		return false;
	}
	return true;
}
/**
 * Makes the primary init. This method allocates the base resources and sets the ServletState and <br>
 * ServletErrorState vaiables which hold the moment state of the servlet and the error(if occured).<br>
 * This method is requested by rwServer with parameters from rwServer's configuraation file.
 * @return ServletState byte - the state the servlet had fallen after execution of this method.
 */
 
public byte wr_rwServerInit(String Iwr_rwLogPath, int IScreenLogLevel, int IFileLogLevel, String Idb_Drivers, String Idb_host, String Idb_user, String Idb_password) {
	wr_rwServerDeInit();
	wr_rwLogPath = Iwr_rwLogPath;
	ScreenLogLevel = IScreenLogLevel;
	FileLogLevel = IFileLogLevel;
	db_Drivers = Idb_Drivers;
	db_host = Idb_host;
	db_user = Idb_user;
	db_password = Idb_password;
	if (wr_rwLog != null)
		wr_rwLog.flush();
	wr_rwLog = null;
	wr_rwLog = LogPrinter.makeLogPrinter(wr_rwLogPath);
	wr_rwLog.setLogLevel(FileLogLevel);
	wr_rwLog.setScreenLogLevel(ScreenLogLevel);
	if (wr_rwLog == null) {
		ServletState = Constants.INIT_ERROR;
		ServletErrorState = Constants.LOG_ERROR;
		return ServletState;
	}
	if (!wr_rwdbConnect()) {
		ServletState = Constants.INIT_ERROR;
		ServletErrorState = Constants.CONN_ERROR;		
		wr_rwLog.log("wr_rw_Server (wr_rwServerInit) : Error in wr_rwServerInit() (dbConnect()).", LogPrinter.ERROR);
		wr_rwLog.flush();
		return ServletState;
	}
	if (!wr_rwCheckTable()) {
		ServletState = Constants.INIT_ERROR;
		ServletErrorState = Constants.TABLES_ERROR;		
		wr_rwLog.log("wr_rw_Server (wr_rwServerInit) : Error in creating tables.", LogPrinter.ERROR);
		wr_rwLog.flush();
		return ServletState;
	} else
		wr_rwLog.log("wr_rw_Server (wr_rwServerInit) : Tables are OK.", LogPrinter.INFO);
	wr_rwLog.log("wr_rw_Server (wr_rwServerInit) : --- Primery init finished. servlet ready to work.", LogPrinter.INFO);
	wr_rwLog.flush();
	ServletState = Constants.READY;
	ServletErrorState = Constants.NO_ERROR;
	return ServletState;
}
/**
 * Updates the requested relation. It updates wr_rwLastCount and wr_rwCounts properties in 'wr_rw_Relations' DB.
 * @return boolean
 *	       <br> result - the result from updating
 * 		   <br> -1 (Constants.No_Key) - if the method failed
 */
private int wr_rwUpdateRelation(long wrKey, long rwKey, int wr_rw_Counts, short marketKey, String TableName) {
	String SQLStat = "UPDATE " + TableName + " SET " + dbFields.db_wr_rwCounts + " = " + dbFields.db_wr_rwCounts + " + " + String.valueOf(wr_rw_Counts) + "," + dbFields.db_wr_rwLastCount + " = '" + new java.sql.Date(System.currentTimeMillis()) + "' WHERE " + dbFields.db_wrKey + " = " + String.valueOf(wrKey) + " AND " + dbFields.db_rwKey + " = " + String.valueOf(rwKey) + " AND " + dbFields.db_marketKey + " = " + String.valueOf(marketKey);
	try {
		if (wr_rwdbConn == null)
			throw new SQLException();
		Statement stmt = wr_rwdbConn.createStatement();
		int result = stmt.executeUpdate(SQLStat);
		stmt.close();
		wr_rwLog.log("wr_rw_Server (wr_rwUpdateRelation) : Res from updating = " + result + ". wrKey = " + wrKey + ", rwKey = " + rwKey + ", marketKey = " + marketKey + " in " + TableName + " table.", LogPrinter.DEBUG);
		return result;
	} catch (SQLException e) {
		if (wr_rwdbReconnect()) {
			wr_rwLog.log("wr_rw_Server (wr_rwUpdateRelation) : db Reconnected.", LogPrinter.INFO);
			wr_rwLog.flush();
			return wr_rwUpdateRelation(wrKey, rwKey, wr_rw_Counts, marketKey, TableName);
		} else {
			wr_rwLog.log("wr_src_Server (wr_rwUpdateRelation) : SQL Statement error - " + SQLStat + " Exception : " + e, LogPrinter.ERROR);
			wr_rwLog.flush();
			return Constants.No_Key;
		}
	} catch (NumberFormatException e) {
		wr_rwLog.log("wr_rw_Server (wr_rwUpdateRelation) : error format - " + SQLStat, LogPrinter.ERROR);
		wr_rwLog.flush();
		return Constants.No_Key;
	}
}
/**
 * Finds in which table is/to be/ strored the info for specific wr_rw relation.
 * @return TableName String - always returnes table name
*/

private String wr_rwWhichTable(long prwKey) {
	String result_Table;
	char p = (char) (prwKey % 256);
	if (p >= 'a' && p <= 'z')
		result_Table = "wr_rw_" + p;
	else
		if (p >= '0' && p <= '9')
			result_Table = "wr_rw_" + Constants.cs_EndNumberTable;
		else
			result_Table = "wr_rw_" + Constants.cs_EndSpecialTable;
	return result_Table;
}
}

