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();
 }
 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();
 }