private ReplicationMasterFile(ReplicationMasterStorageImpl storage, IFile file, string localhost, int port, string[] hosts, bool ack, String pageTimestampFilePath) 
 {         
     this.storage = storage;
     this.file = file;
     this.ack = ack;
     this.localhost = localhost;
     this.port = port;
     mutex = new object();
     replicas = new Replica[hosts.Length];
     rcBuf = new byte[1];
     nHosts = 0;
     if (pageTimestampFilePath != null) { 
         FileParameters fileParameters = storage != null ? storage.fileParameters : new FileParameters(false, false, false, 1024*1024);
         pageTimestampFile = new OSFile(pageTimestampFilePath, fileParameters);
         long fileLength = pageTimestampFile.Length;
         if (fileLength == 0) { 
             pageTimestamps = new int[InitPageTimestampsLength];
         } else {
             pageTimestamps = new int[(int)(fileLength/4)];
             byte[] page = new byte[Page.pageSize];
             int i = 0;
             for (long pos = 0; pos < fileLength; pos += Page.pageSize) { 
                 int rc = pageTimestampFile.Read(pos, page);
                 for (int offs = 0; offs < rc; offs += 4, i++) { 
                     pageTimestamps[i] = Bytes.unpack4(page, offs);
                     if (pageTimestamps[i] > timestamp) { 
                         timestamp = pageTimestamps[i];
                     }
                 }
             }
             if (i != pageTimestamps.Length) { 
                 throw new StorageError(StorageError.ErrorCode.FILE_ACCESS_ERROR);
             }
         }
         dirtyPageTimestampMap = new int[(((pageTimestamps.Length*4 + Page.pageSize - 1) >> Page.pageSizeLog) + 31) >> 5];
         txBuf = new byte[12 + Page.pageSize];
     } else { 
         txBuf = new byte[8 + Page.pageSize];
     }
     for (int i = 0; i < hosts.Length; i++) 
     { 
         replicas[i] = new Replica();
         replicas[i].host = hosts[i];
         Connect(i);
     }
     if (port >= 0) 
     {
         storage.SetProperty("perst.alternative.btree", true); // prevent direct modification of pages
         listenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
         listenSocket.Bind(new IPEndPoint(localhost != null && localhost != "localhost" ? IPAddress.Parse(localhost) : IPAddress.Any, port));          
         listenSocket.Listen(ListenQueueSize);
         listening = true;
         listenThread = new Thread(new ThreadStart(run));
         listenThread.Start();
     }
     watchdogThread = new Thread(new ThreadStart(watchdog));
     watchdogThread.Start();
 }
 /// <summary>
 /// Constructor of replication master file
 /// <param name="storage">replication storage</param>
 /// <param name="file">local file used to store data locally</param>
 /// <param name="asyncBufSize">size of asynchronous buffer</param>
 /// <param name="pageTimestampFile">path to the file with pages timestamps. This file is used for synchronizing
 /// with master content of newly attached node</param>
 /// </summary>
 public AsyncReplicationMasterFile(ReplicationMasterStorageImpl storage, IFile file, int asyncBufSize, String pageTimestampFile)
     : base(storage, file, pageTimestampFile)
 {
     this.asyncBufSize = asyncBufSize;
     start();
 }
 /// <summary>
 /// Constructor of replication master file
 /// <param name="storage">replication storage</param>
 /// <param name="file">local file used to store data locally</param>
 /// <param name="asyncBufSize">size of asynchronous buffer</param>
 /// <param name="pageTimestampFile">path to the file with pages timestamps. This file is used for synchronizing
 /// with master content of newly attached node</param>
 /// </summary>
 public AsyncReplicationMasterFile(ReplicationMasterStorageImpl storage, IFile file, int asyncBufSize, String pageTimestampFile)
     : base(storage, file, pageTimestampFile)
 {
     this.asyncBufSize = asyncBufSize;
     start();
 }
 /// <summary>
 /// Constructor of replication master file
 /// </summary>
 /// <param name="storage">replication storage</param>
 /// <param name="file">local file used to store data locally</param>
 /// <param name="pageTimestampFile">path to the file with pages timestamps. This file is used for synchronizing
 /// with master content of newly attached node</param>
 public ReplicationMasterFile(ReplicationMasterStorageImpl storage, IFile file, String pageTimestampFile) 
 : this(storage, file, storage.localhost, storage.port, storage.hosts, storage.replicationAck, pageTimestampFile)
 {
 }
 private ReplicationMasterFile(ReplicationMasterStorageImpl storage, IFile file, string localhost, int port, string[] hosts, bool ack, String pageTimestampFilePath)
 {
     this.storage   = storage;
     this.file      = file;
     this.ack       = ack;
     this.localhost = localhost;
     this.port      = port;
     mutex          = new object();
     replicas       = new Replica[hosts.Length];
     rcBuf          = new byte[1];
     nHosts         = 0;
     if (pageTimestampFilePath != null)
     {
         FileParameters fileParameters = storage != null ? storage.fileParameters : new FileParameters(false, false, false, 1024 * 1024);
         pageTimestampFile = new OSFile(pageTimestampFilePath, fileParameters);
         long fileLength = pageTimestampFile.Length;
         if (fileLength == 0)
         {
             pageTimestamps = new int[InitPageTimestampsLength];
         }
         else
         {
             pageTimestamps = new int[(int)(fileLength / 4)];
             byte[] page = new byte[Page.pageSize];
             int    i    = 0;
             for (long pos = 0; pos < fileLength; pos += Page.pageSize)
             {
                 int rc = pageTimestampFile.Read(pos, page);
                 for (int offs = 0; offs < rc; offs += 4, i++)
                 {
                     pageTimestamps[i] = Bytes.unpack4(page, offs);
                     if (pageTimestamps[i] > timestamp)
                     {
                         timestamp = pageTimestamps[i];
                     }
                 }
             }
             if (i != pageTimestamps.Length)
             {
                 throw new StorageError(StorageError.ErrorCode.FILE_ACCESS_ERROR);
             }
         }
         dirtyPageTimestampMap = new int[(((pageTimestamps.Length * 4 + Page.pageSize - 1) >> Page.pageSizeLog) + 31) >> 5];
         txBuf = new byte[12 + Page.pageSize];
     }
     else
     {
         txBuf = new byte[8 + Page.pageSize];
     }
     for (int i = 0; i < hosts.Length; i++)
     {
         replicas[i]      = new Replica();
         replicas[i].host = hosts[i];
         Connect(i);
     }
     if (port >= 0)
     {
         storage.SetProperty("perst.alternative.btree", true); // prevent direct modification of pages
         listenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
         listenSocket.Bind(new IPEndPoint(localhost != null && localhost != "localhost" ? IPAddress.Parse(localhost) : IPAddress.Any, port));
         listenSocket.Listen(ListenQueueSize);
         listening    = true;
         listenThread = new Thread(new ThreadStart(run));
         listenThread.Start();
     }
     watchdogThread = new Thread(new ThreadStart(watchdog));
     watchdogThread.Start();
 }
 /// <summary>
 /// Constructor of replication master file
 /// </summary>
 /// <param name="storage">replication storage</param>
 /// <param name="file">local file used to store data locally</param>
 /// <param name="pageTimestampFile">path to the file with pages timestamps. This file is used for synchronizing
 /// with master content of newly attached node</param>
 public ReplicationMasterFile(ReplicationMasterStorageImpl storage, IFile file, String pageTimestampFile)
     : this(storage, file, storage.localhost, storage.port, storage.hosts, storage.replicationAck, pageTimestampFile)
 {
 }