private long SendBlockTo(BlockId blockId, IServiceAddress destAddress, long destServerId, IServiceAddress[] managerServers) { lock (service.processLock) { long processId = service.processIdSeq++; SendBlockInfo info = new SendBlockInfo(processId, blockId, destAddress, destServerId, managerServers); // Schedule the process to happen immediately (or as immediately as // possible). new Timer(SendBlockToTask, info, 0, Timeout.Infinite); return(processId); } }
private void SendBlockToTask(object state) { SendBlockInfo info = (SendBlockInfo)state; // Connect to the destination service address, IMessageProcessor p = service.Connector.Connect(info.Destination, ServiceType.Block); int blockType = service.DiscoverBlockType(info.BlockId); if (blockType == -1) { return; } BlockData data = service.GetBlockData(info.BlockId, blockType); // If the data was not found, exit, if (!data.Exists) { return; } try { BlockContainer blockContainer = service.FetchBlockContainer(info.BlockId); // If the block was written to less than 6 minutes ago, we don't allow // the copy to happen, if (!service.IsKnownStaticBlock(blockContainer)) { // This will happen if this block server has not be notified // recently by the managers the maximum block id they are managing. service.Logger.Info(String.Format("Can't copy last block_id ( {0} ) on server, it's not a known static block.", info.BlockId)); return; } IEnumerable <Message> inputStream; Message ouputMessage; // If the file does exist, push it over, byte[] buf = new byte[16384]; int pos = 0; Stream fin = data.OpenRead(); while (true) { int read = fin.Read(buf, 0, buf.Length); // Exit if we reached the end of the file, if (read == 0) { break; } ouputMessage = new Message("sendBlockPart", info.BlockId, pos, blockType, buf, read); // Process the message, inputStream = p.Process(ouputMessage.AsStream()); // Get the input iterator, foreach (Message m in inputStream) { if (m.HasError) { service.Logger.Info(String.Format("'sendBlockPart' command error: {0}", m.ErrorMessage)); return; } } pos += read; } // Close, fin.Close(); // Send the 'complete' command, ouputMessage = new Message("sendBlockComplete", info.BlockId, blockType); // Process the message, inputStream = p.Process(ouputMessage.AsStream()); // Get the input iterator, foreach (Message m in inputStream) { if (m.HasError) { service.Logger.Info(String.Format("'sendBlockCommand' command error: {0}", m.ErrorMessage)); return; } } // Tell the manager server about this new block mapping, ouputMessage = new Message("internalAddBlockServerMapping", info.BlockId, new long[] { info.DestinationServerId }); service.Logger.Info(String.Format("Adding block_id->server mapping ({0} -> {1})", info.BlockId, info.DestinationServerId)); for (int n = 0; n < info.ManagerServers.Length; ++n) { // Process the message, IMessageProcessor mp = service.Connector.Connect(info.ManagerServers[n], ServiceType.Manager); inputStream = mp.Process(ouputMessage.AsStream()); // Get the input iterator, foreach (Message m in inputStream) { if (m.HasError) { service.Logger.Info(String.Format("'internalAddBlockServerMapping' command error: @ {0} - {1}", info.ManagerServers[n], m.ErrorMessage)); break; } } } } catch (IOException e) { service.Logger.Info(e); } }