protected override Message Deserialize(BinaryReader reader, MessageType messageType) { int type = reader.ReadInt32(); if (type == 2) { MessageStream stream = new MessageStream(messageType); int sz = reader.ReadInt32(); for (int i = 0; i < sz; i++) { stream.AddMessage(Deserialize(reader, messageType)); } return stream as Message; } if (type == 1) { Message message; string messageName = reader.ReadString(); if (messageType == MessageType.Request) { message = new RequestMessage(messageName); } else { message = new ResponseMessage(messageName); } int sz = reader.ReadInt32(); for (int i = 0; i < sz; i++) message.Arguments.Add(ReadArgument(reader)); int v = reader.ReadInt32(); if (v != 8) throw new FormatException(); return message; } throw new FormatException("Unable to determine the format of the message."); }
public void RequestMessageStreamSerialize() { MessageStream requestStream = MessageStream.NewRequest(); RequestMessage request = new RequestMessage("testMethod1"); request.Arguments.Add(true); requestStream.AddMessage(request); request = new RequestMessage("testMethod2"); request.Arguments.Add("test"); request.Arguments.Add(false); requestStream.AddMessage(request); string s = Serialize(requestStream); StringBuilder sb = new StringBuilder(); sb.Append("<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>"); sb.Append("<messageStream>"); sb.Append("<message>"); sb.Append("<methodCall>"); sb.Append("<methodName>testMethod1</methodName>"); sb.Append("<params><param><value><boolean>1</boolean></value></param></params>"); sb.Append("</methodCall>"); sb.Append("</message>"); sb.Append("<message>"); sb.Append("<methodCall>"); sb.Append("<methodName>testMethod2</methodName>"); sb.Append("<params><param><value><string>test</string></value></param><param><value><boolean>0</boolean></value></param></params>"); sb.Append("</methodCall>"); sb.Append("</message>"); sb.Append("</messageStream>"); Console.Out.WriteLine("Generated:"); Console.Out.WriteLine(s); Assert.AreEqual(sb.ToString(), s); }
public IList<ITreeNode> FetchNodes(NodeId[] nids) { // The number of nodes, int nodeCount = nids.Length; // The array of read nodes, ITreeNode[] resultNodes = new ITreeNode[nodeCount]; // Resolve special nodes first, { int i = 0; foreach (NodeId nodeId in nids) { if (nodeId.IsSpecial) { resultNodes[i] = nodeId.CreateSpecialTreeNode(); } ++i; } } // Group all the nodes to the same block, List<BlockId> uniqueBlocks = new List<BlockId>(); List<List<NodeId>> uniqueBlockList = new List<List<NodeId>>(); { int i = 0; foreach (NodeId nodeId in nids) { // If it's not a special node, if (!nodeId.IsSpecial) { // Get the block id and add it to the list of unique blocks, DataAddress address = new DataAddress(nodeId); // Check if the node is in the local cache, ITreeNode node = networkCache.GetNode(address); if (node != null) { resultNodes[i] = node; } else { // Not in the local cache so we need to bundle this up in a node // request on the block servers, // Group this node request by the block identifier BlockId blockId = address.BlockId; int ind = uniqueBlocks.IndexOf(blockId); if (ind == -1) { ind = uniqueBlocks.Count; uniqueBlocks.Add(blockId); uniqueBlockList.Add(new List<NodeId>()); } List<NodeId> blist = uniqueBlockList[ind]; blist.Add(nodeId); } } ++i; } } // Exit early if no blocks, if (uniqueBlocks.Count == 0) { return resultNodes; } // Resolve server records for the given block identifiers, IDictionary<BlockId, IList<BlockServerElement>> serversMap = GetServerListForBlocks(uniqueBlocks); // The result nodes list, List<ITreeNode> nodes = new List<ITreeNode>(); // Checksumming objects byte[] checksumBuf = null; Crc32 crc32 = null; // For each unique block list, foreach (List<NodeId> blist in uniqueBlockList) { // Make a block server request for each node in the block, MessageStream blockServerMsg = new MessageStream(); BlockId blockId = null; foreach (NodeId nodeId in blist) { DataAddress address = new DataAddress(nodeId); blockServerMsg.AddMessage(new Message("readFromBlock", address)); blockId = address.BlockId; } if (blockId == null) { throw new ApplicationException("block_id == null"); } // Get the shuffled list of servers the block is stored on, IList<BlockServerElement> servers = serversMap[blockId]; // Go through the servers one at a time to fetch the block, bool success = false; for (int z = 0; z < servers.Count && !success; ++z) { BlockServerElement server = servers[z]; // If the server is up, if (server.IsStatusUp) { // Open a connection with the block server, IMessageProcessor blockServerProc = connector.Connect(server.Address, ServiceType.Block); IEnumerable<Message> messageIn = blockServerProc.Process(blockServerMsg); ++NetworkCommCount; ++NetworkFetchCommCount; bool isError = false; bool severeError = false; bool crcError = false; bool connectionError = false; // Turn each none-error message into a node foreach (Message m in messageIn) { if (m.HasError) { // See if this error is a block read error. If it is, we don't // tell the manager server to lock this server out completely. bool isBlockReadError = m.Error.Source.Equals("Deveel.Data.Net.BlockReadException"); // If it's a connection fault, if (IsConnectionFailMessage(m)) { connectionError = true; } else if (!isBlockReadError) { // If it's something other than a block read error or // connection failure, we set the severe flag, severeError = true; } isError = true; } else if (isError == false) { // The reply contains the block of data read. NodeSet nodeSet = (NodeSet) m.Arguments[0].Value; DataAddress address = null; // Catch any IOExceptions (corrupt zips, etc) try { // Decode the node items into Java node objects, foreach (Node nodeItem in nodeSet) { NodeId nodeId = nodeItem.Id; address = new DataAddress(nodeId); // Wrap around a buffered DataInputStream for reading values // from the store. BinaryReader input = new BinaryReader(nodeItem.Input); short nodeType = input.ReadInt16(); ITreeNode readNode = null; if (crc32 == null) crc32 = new Crc32(); crc32.Initialize(); // Is the node type a leaf node? if (nodeType == StoreLeafType) { // Read the checksum, input.ReadInt16(); // For future use... int checksum = input.ReadInt32(); // Read the size int leafSize = input.ReadInt32(); byte[] buf = StreamUtil.AsBuffer(nodeItem.Input); if (buf == null) { buf = new byte[leafSize + 12]; ByteBuffer.WriteInt4(leafSize, buf, 8); input.Read(buf, 12, leafSize); } // Check the checksum... crc32.ComputeHash(buf, 8, leafSize + 4); int calcChecksum = (int) crc32.CrcValue; if (checksum != calcChecksum) { // If there's a CRC failure, we reject his node, log.Warning(String.Format("CRC failure on node {0} @ {1}", nodeId, server.Address)); isError = true; crcError = true; // This causes the read to retry on a different server // with this block id } else { // Create a leaf that's mapped to this data ITreeNode leaf = new MemoryTreeLeaf(nodeId, buf); readNode = leaf; } } // Is the node type a branch node? else if (nodeType == StoreBranchType) { // Read the checksum, input.ReadInt16(); // For future use... int checksum = input.ReadInt32(); // Check the checksum objects, if (checksumBuf == null) checksumBuf = new byte[8]; // Note that the entire branch is loaded into memory, int childDataSize = input.ReadInt32(); ByteBuffer.WriteInt4(childDataSize, checksumBuf, 0); crc32.ComputeHash(checksumBuf, 0, 4); long[] dataArr = new long[childDataSize]; for (int n = 0; n < childDataSize; ++n) { long item = input.ReadInt64(); ByteBuffer.WriteInt8(item, checksumBuf, 0); crc32.ComputeHash(checksumBuf, 0, 8); dataArr[n] = item; } // The calculated checksum value, int calcChecksum = (int) crc32.CrcValue; if (checksum != calcChecksum) { // If there's a CRC failure, we reject his node, log.Warning(String.Format("CRC failure on node {0} @ {1}", nodeId, server.Address)); isError = true; crcError = true; // This causes the read to retry on a different server // with this block id } else { // Create the branch node, TreeBranch branch = new TreeBranch(nodeId, dataArr, childDataSize); readNode = branch; } } else { log.Error(String.Format("Unknown node {0} type: {1}", address, nodeType)); isError = true; } // Is the node already in the list? If so we don't add it. if (readNode != null && !IsInNodeList(nodeId, nodes)) { // Put the read node in the cache and add it to the 'nodes' // list. networkCache.SetNode(address, readNode); nodes.Add(readNode); } } // while (item_iterator.hasNext()) } catch (IOException e) { // This catches compression errors, as well as any other misc // IO errors. if (address != null) { log.Error(String.Format("IO Error reading node {0}", address)); } log.Error(e.Message, e); isError = true; } } } // for (Message m : message_in) // If there was no error while reading the result, we assume the node // requests were successfully read. if (isError == false) { success = true; } else { // If this is a connection failure, we report the block failure. if (connectionError) { // If this is an error, we need to report the failure to the // manager server, ReportBlockServerFailure(server.Address); // Remove the block id from the server list cache, networkCache.RemoveServersWithBlock(blockId); } else { String failType = "General"; if (crcError) { failType = "CRC Failure"; } else if (severeError) { failType = "Exception during process"; } // Report to the first manager the block failure, so it may // investigate and hopefully correct. ReportBlockIdCorruption(server.Address, blockId, failType); // Otherwise, not a severe error (probably a corrupt block on a // server), so shuffle the server list for this block_id so next // time there's less chance of hitting this bad block. IEnumerable<BlockServerElement> srvs = networkCache.GetServersWithBlock(blockId); if (srvs != null) { List<BlockServerElement> serverList = new List<BlockServerElement>(); serverList.AddRange(srvs); CollectionsUtil.Shuffle(serverList); networkCache.SetServersForBlock(blockId, serverList, 15*60*1000); } } // We will now go retry the query on the next block server, } } } // If the nodes were not successfully read, we generate an exception, if (!success) { // Remove from the cache, networkCache.RemoveServersWithBlock(blockId); throw new ApplicationException( "Unable to fetch node from a block server" + " (block = " + blockId + ")"); } } int sz = nodes.Count; if (sz == 0) { throw new ApplicationException("Empty nodes list"); } for (int i = 0; i < sz; ++i) { ITreeNode node = nodes[i]; NodeId nodeId = node.Id; for (int n = 0; n < nids.Length; ++n) { if (nids[n].Equals(nodeId)) { resultNodes[n] = node; } } } // Check the result_nodes list is completely populated, for (int n = 0; n < resultNodes.Length; ++n) { if (resultNodes[n] == null) { throw new ApplicationException("Assertion failed: result_nodes not completely populated."); } } return resultNodes; }
private IDictionary<long, IList<BlockServerElement>> GetServersForBlock(IList<long> blockIds) { // The result map, Dictionary<long, IList<BlockServerElement>> resultMap = new Dictionary<long, IList<BlockServerElement>>(); List<long> noneCached = new List<long>(blockIds.Count); foreach (long blockId in blockIds) { IList<BlockServerElement> v = networkCache.GetServers(blockId); // If it's cached (and the cache is current), if (v != null) { resultMap.Add(blockId, v); } // If not cached, add to the list of none cached entries, else { noneCached.Add(blockId); } } // If there are no 'none_cached' blocks, if (noneCached.Count == 0) // Return the result, return resultMap; // Otherwise, we query the manager server for current records on the given // blocks. IMessageProcessor manager = connector.Connect(managerAddress, ServiceType.Manager); MessageStream message_out = new MessageStream(MessageType.Request); foreach (long block_id in noneCached) { RequestMessage request = new RequestMessage("getServerListForBlock"); request.Arguments.Add(block_id); message_out.AddMessage(request); } MessageStream message_in = (MessageStream) manager.Process(message_out); int n = 0; foreach (ResponseMessage m in message_in) { if (m.HasError) throw new Exception(m.ErrorMessage, m.Error.AsException()); int sz = m.Arguments[0].ToInt32(); List<BlockServerElement> srvs = new List<BlockServerElement>(sz); IServiceAddress[] addresses = (IServiceAddress[]) m.Arguments[1].Value; int[] status = (int[]) m.Arguments[2].Value; for (int i = 0; i < sz; ++i) { srvs.Add(new BlockServerElement(addresses[i], (ServiceStatus) status[i])); } // Shuffle the list CollectionsUtil.Shuffle(srvs); // Move the server closest to this node to the start of the list, int closest = 0; int cur_close_factor = Int32.MaxValue; for (int i = 0; i < sz; ++i) { BlockServerElement elem = srvs[i]; int closeness_factor = GetProximity(elem.Address); if (closeness_factor < cur_close_factor) { cur_close_factor = closeness_factor; closest = i; } } // Swap if necessary, if (closest > 0) { CollectionsUtil.Swap(srvs, 0, closest); } // Put it in the result map, long block_id = noneCached[n]; resultMap.Add(block_id, srvs); // Add it to the cache, // NOTE: TTL hard-coded to 15 minute networkCache.SetServers(block_id, srvs, 15*60*1000); ++n; } // Return the list return resultMap; }
public IList<ITreeNode> FetchNodes(long[] nids) { // The number of nodes, int node_count = nids.Length; // The array of read nodes, ITreeNode[] result_nodes = new ITreeNode[node_count]; // Resolve special nodes first, { int i = 0; foreach (long nodeId in nids) { if ((nodeId & 0x01000000000000000L) != 0) result_nodes[i] = SparseLeafNode.Create(nodeId); ++i; } } // Group all the nodes to the same block, List<long> uniqueBlocks = new List<long>(); List<List<long>> uniqueBlockList = new List<List<long>>(); { int i = 0; foreach (long node_ref in nids) { // If it's not a special node, if ((node_ref & 0x01000000000000000L) == 0) { // Get the block id and add it to the list of unique blocks, DataAddress address = new DataAddress(node_ref); // Check if the node is in the local cache, ITreeNode node = networkCache.GetNode(address); if (node != null) { result_nodes[i] = node; } else { // Not in the local cache so we need to bundle this up in a node // request on the block servers, // Group this node request by the block identifier long blockId = address.BlockId; int ind = uniqueBlocks.IndexOf(blockId); if (ind == -1) { ind = uniqueBlocks.Count; uniqueBlocks.Add(blockId); uniqueBlockList.Add(new List<long>()); } List<long> blist = uniqueBlockList[ind]; blist.Add(node_ref); } } ++i; } } // Exit early if no blocks, if (uniqueBlocks.Count == 0) return result_nodes; // Resolve server records for the given block identifiers, IDictionary<long, IList<BlockServerElement>> servers_map = GetServersForBlock(uniqueBlocks); // The result nodes list, List<ITreeNode> nodes = new List<ITreeNode>(); // For each unique block list, foreach (List<long> blist in uniqueBlockList) { // Make a block server request for each node in the block, MessageStream block_server_msg = new MessageStream(MessageType.Request); long block_id = -1; foreach (long node_ref in blist) { DataAddress address = new DataAddress(node_ref); RequestMessage request = new RequestMessage("readFromBlock"); request.Arguments.Add(address); block_server_msg.AddMessage(request); block_id = address.BlockId; } if (block_id == -1) throw new ApplicationException("block_id == -1"); // Get the shuffled list of servers the block is stored on, IList<BlockServerElement> servers = servers_map[block_id]; // Go through the servers one at a time to fetch the block, bool success = false; for (int z = 0; z < servers.Count && !success; ++z) { BlockServerElement server = servers[z]; // If the server is up, if (server.IsStatusUp) { // Open a connection with the block server, IMessageProcessor block_server_proc = connector.Connect(server.Address, ServiceType.Block); MessageStream message_in = (MessageStream) block_server_proc.Process(block_server_msg); // DEBUG: ++networkCommCount; // DEBUG: ++networkFetchCommCount; bool is_error = false; bool severe_error = false; // Turn each none-error message into a node foreach (ResponseMessage m in message_in) { if (m.HasError) { // See if this error is a block read error. If it is, we don't // tell the manager server to lock this server out completely. bool is_block_read_error = m.Error.Source.Equals("Deveel.Data.Net.BlockReadException"); if (!is_block_read_error) { // If it's something other than a block read error, we mark // this error as severe, severe_error = true; } is_error = true; } else if (!is_error) { // The reply contains the block of data read. NodeSet node_set = (NodeSet)m.Arguments[0].Value; // Decode the node items into node objects, IEnumerator<Node> item_iterator = node_set.GetEnumerator(); while (item_iterator.MoveNext()) { // Get the node item, Node node_item = item_iterator.Current; long node_ref = node_item.Id; DataAddress address = new DataAddress(node_ref); // Wrap around a buffered DataInputStream for reading values // from the store. BinaryReader input = new BinaryReader(node_item.Input, Encoding.Unicode); short node_type = input.ReadInt16(); ITreeNode read_node; // Is the node type a leaf node? if (node_type == LeafType) { // Read the key int leaf_size = input.ReadInt32(); byte[] buf = ReadNodeAsBuffer(node_item); if (buf == null) { buf = new byte[leaf_size + 6]; input.Read(buf, 6, leaf_size); // Technically, we could comment these next two lines out. ByteBuffer.WriteInt2(node_type, buf, 0); ByteBuffer.WriteInt4(leaf_size, buf, 2); } // Create a leaf that's mapped to this data read_node = new ByteArrayTreeLeaf(node_ref, buf); ; } // Is the node type a branch node? else if (node_type == BranchType) { // Note that the entire branch is loaded into memory, int child_data_size = input.ReadInt32(); long[] data_arr = new long[child_data_size]; for (int n = 0; n < child_data_size; ++n) { data_arr[n] = input.ReadInt64(); } // Create the branch node, read_node = new TreeBranch(node_ref, data_arr, child_data_size); } else { throw new InvalidDataState("Unknown node type: " + node_type, address); } // Is the node already in the list? If so we don't add it. if (!IsInNodeList(node_ref, nodes)) { // Put the read node in the cache and add it to the 'nodes' // list. networkCache.SetNode(address, read_node); nodes.Add(read_node); } } } } // If there was no error while reading the result, we assume the node // requests were successfully read. if (is_error == false) { success = true; } else { if (severe_error) { // If this is an error, we need to report the failure to the // manager server, ReportBlockServerFailure(server.Address); // Remove the block id from the server list cache, networkCache.RemoveServers(block_id); } else { // Otherwise, not a severe error (probably a corrupt block on a // server), so shuffle the server list for this block_id so next // time there's less chance of hitting this bad block. IList<BlockServerElement> srvs = networkCache.GetServers(block_id); List<BlockServerElement> server_list = new List<BlockServerElement>(); server_list.AddRange(srvs); CollectionsUtil.Shuffle(server_list); networkCache.SetServers(block_id, server_list, 15 * 60 * 1000); } } } } // If the nodes were not successfully read, we generate an exception, if (!success) { // Remove from the cache, networkCache.RemoveServers(block_id); throw new ApplicationException("Unable to fetch node from block server"); } } int sz = nodes.Count; if (sz == 0) throw new ApplicationException("Empty nodes list"); for (int i = 0; i < sz; ++i) { ITreeNode node = nodes[i]; long node_ref = node.Id; for (int n = 0; n < nids.Length; ++n) { if (nids[n] == node_ref) result_nodes[n] = node; } } // Check the result_nodes list is completely populated, for (int n = 0; n < result_nodes.Length; ++n) { if (result_nodes[n] == null) throw new ApplicationException("Assertion failed: result_nodes not completely populated."); } return result_nodes; }
private void PollAllRootMachines(IServiceAddress[] machines) { // Create the message, MessageStream outputStream = new MessageStream(); outputStream.AddMessage(new Message("poll", "RSPoll")); for (int i = 0; i < machines.Length; ++i) { IServiceAddress machine = machines[i]; // If the service is up in the tracker, if (serviceTracker.IsServiceUp(machine, ServiceType.Root)) { // Poll it to see if it's really up. // Send the poll to the service, IMessageProcessor processor = connector.Connect(machine, ServiceType.Root); IEnumerable<Message> inputStream = processor.Process(outputStream); // If return is a connection fault, foreach (Message m in inputStream) { if (m.HasError && ReplicatedValueStore.IsConnectionFault(m)) { serviceTracker.ReportServiceDownClientReport(machine, ServiceType.Root); } } } } }
public IEnumerable<Message> Process(IEnumerable<Message> stream) { // The reply message, MessageStream replyMessage = new MessageStream(); // The messages in the stream, foreach (Message m in stream) { try { service.CheckErrorState(); // publishPath(string, long, DataAddress) if (m.Name.Equals("publishPath")) { PublishPath((String) m.Arguments[0].Value, (int) m.Arguments[1].Value, (DataAddress) m.Arguments[2].Value); replyMessage.AddMessage(new Message(1L)); } // DataAddress getPathNow(String, long) else if (m.Name.Equals("getPathNow")) { DataAddress dataAddress = GetPathNow((string)m.Arguments[0].Value, (int)m.Arguments[1].Value); replyMessage.AddMessage(new Message(dataAddress)); } // DataAddress[] getPathHistorical(string, long, long, long) else if (m.Name.Equals("getPathHistorical")) { DataAddress[] dataAddresses = GetPathHistorical((string) m.Arguments[0].Value, (int) m.Arguments[1].Value, (long) m.Arguments[2].Value, (long) m.Arguments[3].Value); replyMessage.AddMessage(new Message(new object[] {dataAddresses})); } // long getCurrentTimeMillis() else if (m.Name.Equals("getCurrentTimeMillis")) { long timeMillis = DateTimeUtil.CurrentTimeMillis(); replyMessage.AddMessage(new Message(timeMillis)); } // commit(string, long, DataAddress) else if (m.Name.Equals("commit")) { DataAddress result = Commit((string) m.Arguments[0].Value, (int) m.Arguments[1].Value, (DataAddress) m.Arguments[2].Value); replyMessage.AddMessage(new Message(result)); } // getPathType(String path) else if (m.Name.Equals("getPathType")) { string pathType = service.GetPathType((string)m.Arguments[0].Value); replyMessage.AddMessage(new Message(pathType)); } // initialize(string, long) else if (m.Name.Equals("initialize")) { Initialize((string)m.Arguments[0].Value, (int)m.Arguments[1].Value); replyMessage.AddMessage(new Message(1L)); } // getPathStats(string, long) else if (m.Name.Equals("getPathStats")) { String stats = GetPathStats((string)m.Arguments[0].Value, (int)m.Arguments[1].Value); replyMessage.AddMessage(new Message(stats)); } // getSnapshotStats(string, long, DataAddress) else if (m.Name.Equals("getSnapshotStats")) { String stats = GetSnapshotStats((string)m.Arguments[0].Value, (int)m.Arguments[1].Value, (DataAddress)m.Arguments[2].Value); replyMessage.AddMessage(new Message(stats)); } // checkCPathType(string) else if (m.Name.Equals("checkPathType")) { CheckPathType((string)m.Arguments[0].Value); replyMessage.AddMessage(new Message(1)); } // informOfManagers(ServiceAddress[] manager_servers) else if (m.Name.Equals("informOfManagers")) { service.OnManagersSet((IServiceAddress[])m.Arguments[0].Value); replyMessage.AddMessage(new Message(1L)); } // clearOfManagers() else if (m.Name.Equals("clearOfManagers")) { service.OnManagersClear(); replyMessage.AddMessage(new Message(1L)); } // loadPathInfo(PathInfo) else if (m.Name.Equals("loadPathInfo")) { service.LoadPathInfo((PathInfo)m.Arguments[0].Value); replyMessage.AddMessage(new Message(1L)); } // notifyNewProposal(string, long, DataAddress) else if (m.Name.Equals("notifyNewProposal")) { service.NotifyNewProposal((string) m.Arguments[0].Value, (long) m.Arguments[1].Value, (DataAddress) m.Arguments[2].Value); replyMessage.AddMessage(new Message(1L)); } // internalSetPathInfo(String path_name, long ver, PathInfo path_info) else if (m.Name.Equals("internalSetPathInfo")) { service.InternalSetPathInfo((string) m.Arguments[0].Value, (int) m.Arguments[1].Value, (PathInfo) m.Arguments[2].Value); replyMessage.AddMessage(new Message(1L)); } // internalFetchPathDataBundle(String path_name, // long uid, DataAddress addr) else if (m.Name.Equals("internalFetchPathDataBundle")) { object[] r = service.InternalFetchPathDataBundle((string) m.Arguments[0].Value, (long) m.Arguments[1].Value, (DataAddress) m.Arguments[2].Value); replyMessage.AddMessage(new Message(r)); } // poll() else if (m.Name.Equals("poll")) { replyMessage.AddMessage(new Message(1)); } else { throw new ApplicationException("Unknown command: " + m.Name); } } catch (OutOfMemoryException e) { service.Logger.Error("Memory Error", e); service.SetErrorState(e); throw; } catch (Exception e) { service.Logger.Error("Exception during process", e); replyMessage.AddMessage(new Message(new MessageError(e))); } } return replyMessage; }
public IEnumerable <Message> Process(IEnumerable <Message> request) { // The message output, MessageStream response = new MessageStream(); // For each message in the message input, foreach (Message m in request) { try { string command = m.Name; // Report on the services running, if (command.Equals("report")) { lock (service.serverManagerLock) { long tm = System.Diagnostics.Process.GetCurrentProcess().PrivateMemorySize64; long fm = 0 /* TODO: GetFreeMemory()*/; long td = 0 /* TODO: GetTotalSpace(service.basePath) */; long fd = 0 /* TODO: GetUsableSpace(service.basePath)*/; MachineRoles roles = MachineRoles.None; Message message = new Message(); if (service.block != null) { roles |= MachineRoles.Block; } if (service.manager != null) { roles |= MachineRoles.Manager; } if (service.root != null) { roles |= MachineRoles.Root; } message.Arguments.Add((byte)roles); message.Arguments.Add(tm - fm); message.Arguments.Add(tm); message.Arguments.Add(td - fd); message.Arguments.Add(td); response.AddMessage(message); } } else if (command.Equals("reportStats")) { // Analytics stats; we convert the stats to a long[] array and // send it as a reply. long[] stats = GetStats(); response.AddMessage(new Message(new object[] { stats })); } else { // Starts a service, if (command.Equals("start")) { ServiceType serviceType = (ServiceType)(byte)m.Arguments[0].Value; service.StartService(serviceType); } // Stops a service, else if (command.Equals("stop")) { ServiceType serviceType = (ServiceType)(byte)m.Arguments[0].Value; service.StopService(serviceType); } else { throw new ApplicationException("Unknown command: " + command); } // Add reply message, response.AddMessage(new Message(1L)); } } catch (OutOfMemoryException e) { service.Logger.Error("Out-Of-Memory", e); // This will end the connection throw; } catch (Exception e) { service.Logger.Error("Exception during process", e); response.AddMessage(new Message(new MessageError(e))); } } return(response); }
public void Process(Message m, MessageStream replyMessage) { String cmd = m.Name; if (cmd.Equals("internalKVProposal")) { long[] uid = (long[]) m.Arguments[0].Value; String key = (String) m.Arguments[1].Value; String value = (String) m.Arguments[2].Value; InternalKvProposal(uid, key, value); replyMessage.AddMessage(new Message(1)); } else if (cmd.Equals("internalKVComplete")) { long[] uid = (long[]) m.Arguments[0].Value; String key = (String) m.Arguments[1].Value; String value = (String) m.Arguments[2].Value; InternalKvComplete(uid, key, value); replyMessage.AddMessage(new Message(1)); } else if (cmd.Equals("internalBSProposal")) { long[] uid = (long[]) m.Arguments[0].Value; BlockId blockId = (BlockId) m.Arguments[1].Value; long[] serverUids = (long[]) m.Arguments[2].Value; InternalBsProposal(uid, blockId, serverUids); replyMessage.AddMessage(new Message(1)); } else if (cmd.Equals("internalBSComplete")) { long[] uid = (long[]) m.Arguments[0].Value; BlockId blockId = (BlockId) m.Arguments[1].Value; long[] serverUids = (long[]) m.Arguments[2].Value; InternalBsComplete(uid, blockId, serverUids); replyMessage.AddMessage(new Message(1)); } else if (cmd.Equals("internalFetchLogBundle")) { long[] uid = (long[]) m.Arguments[0].Value; bool initial = ((int) m.Arguments[1].Value) != 0; InternalFetchLogBundle(replyMessage, uid, initial); } else if (cmd.Equals("debugString")) { StringWriter strOut = new StringWriter(); DebugOutput(strOut); strOut.Flush(); replyMessage.AddMessage(new Message(strOut.ToString())); } else { throw new ApplicationException("Unknown command: " + m.Name); } }
private NodeId[] InternalPersist(TreeWrite sequence, int tryCount) { // NOTE: nodes are written in order of branches and then leaf nodes. All // branch nodes and leafs are grouped together. // The list of nodes to be allocated, IList<ITreeNode> allBranches = sequence.BranchNodes; IList<ITreeNode> allLeafs = sequence.LeafNodes; List<ITreeNode> nodes = new List<ITreeNode>(allBranches.Count + allLeafs.Count); nodes.AddRange(allBranches); nodes.AddRange(allLeafs); int sz = nodes.Count; // The list of allocated referenced for the nodes, DataAddress[] refs = new DataAddress[sz]; NodeId[] outNodeIds = new NodeId[sz]; MessageStream allocateMessageStream = new MessageStream(); // Allocate the space first, for (int i = 0; i < sz; ++i) { ITreeNode node = nodes[i]; // Is it a branch node? if (node is TreeBranch) { // Branch nodes are 1K in size, allocateMessageStream.AddMessage(new Message("allocateNode", 1024)); } // Otherwise, it must be a leaf node, else { // Leaf nodes are 4k in size, allocateMessageStream.AddMessage(new Message("allocateNode", 4096)); } } // Process a command on the manager, IEnumerable<Message> resultStream = ProcessManager(allocateMessageStream); // The unique list of blocks, List<BlockId> uniqueBlocks = new List<BlockId>(); // Parse the result stream one message at a time, the order will be the // order of the allocation messages, int n = 0; foreach (Message m in resultStream) { if (m.HasError) throw new ApplicationException(m.ErrorMessage); DataAddress addr = (DataAddress) m.Arguments[0].Value; refs[n] = addr; // Make a list of unique block identifiers, if (!uniqueBlocks.Contains(addr.BlockId)) { uniqueBlocks.Add(addr.BlockId); } ++n; } // Get the block to server map for each of the blocks, IDictionary<BlockId, IList<BlockServerElement>> blockToServerMap = GetServerListForBlocks(uniqueBlocks); // Make message streams for each unique block int ubidCount = uniqueBlocks.Count; MessageStream[] ubidStream = new MessageStream[ubidCount]; for (int i = 0; i < ubidStream.Length; ++i) { ubidStream[i] = new MessageStream(); } // Scan all the blocks and create the message streams, for (int i = 0; i < sz; ++i) { byte[] nodeBuf; ITreeNode node = nodes[i]; // Is it a branch node? if (node is TreeBranch) { TreeBranch branch = (TreeBranch) node; // Make a copy of the branch (NOTE; we clone() the array here). long[] curNodeData = (long[]) branch.NodeData.Clone(); int curNdsz = branch.NodeDataSize; branch = new TreeBranch(refs[i].Value, curNodeData, curNdsz); // The number of children int chsz = branch.ChildCount; // For each child, if it's a heap node, look up the child id and // reference map in the sequence and set the reference accordingly, for (int o = 0; o < chsz; ++o) { NodeId childId = branch.GetChild(o); if (childId.IsInMemory) { // The ref is currently on the heap, so adjust accordingly int refId = sequence.LookupRef(i, o); branch.SetChildOverride(refs[refId].Value, o); } } // Turn the branch into a 'node_buf' byte[] array object for // serialization. long[] nodeData = branch.NodeData; int ndsz = branch.NodeDataSize; MemoryStream bout = new MemoryStream(1024); BinaryWriter dout = new BinaryWriter(bout); dout.Write(StoreBranchType); dout.Write((short) 0); // Reserved for future dout.Write(0); // The crc32 checksum will be written here, dout.Write(ndsz); for (int o = 0; o < ndsz; ++o) { dout.Write(nodeData[o]); } dout.Flush(); // Turn it into a byte array, nodeBuf = bout.ToArray(); // Write the crc32 of the data, Crc32 checksum = new Crc32(); checksum.ComputeHash(nodeBuf, 8, nodeBuf.Length - 8); ByteBuffer.WriteInt4((int) checksum.CrcValue, nodeBuf, 4); // Put this branch into the local cache, networkCache.SetNode(refs[i], branch); } // If it's a leaf node, else { TreeLeaf leaf = (TreeLeaf) node; int lfsz = leaf.Length; nodeBuf = new byte[lfsz + 12]; // Format the data, ByteBuffer.WriteInt2(StoreLeafType, nodeBuf, 0); ByteBuffer.WriteInt2(0, nodeBuf, 2); // Reserved for future ByteBuffer.WriteInt4(lfsz, nodeBuf, 8); leaf.Read(0, nodeBuf, 12, lfsz); // Calculate and set the checksum, Crc32 checksum = new Crc32(); checksum.ComputeHash(nodeBuf, 8, nodeBuf.Length - 8); ByteBuffer.WriteInt4((int) checksum.CrcValue, nodeBuf, 4); // Put this leaf into the local cache, leaf = new MemoryTreeLeaf(refs[i].Value, nodeBuf); networkCache.SetNode(refs[i], leaf); } // The DataAddress this node is being written to, DataAddress address = refs[i]; // Get the block id, BlockId blockId = address.BlockId; int bid = uniqueBlocks.IndexOf(blockId); ubidStream[bid].AddMessage(new Message("writeToBlock", address, nodeBuf, 0, nodeBuf.Length)); // Update 'out_refs' array, outNodeIds[i] = refs[i].Value; } // A log of successfully processed operations, List<object> successProcess = new List<object>(64); // Now process the streams on the servers, for (int i = 0; i < ubidStream.Length; ++i) { // The output message, MessageStream outputStream = ubidStream[i]; // Get the servers this message needs to be sent to, BlockId blockId = uniqueBlocks[i]; IList<BlockServerElement> blockServers = blockToServerMap[blockId]; // Format a message for writing this node out, int bssz = blockServers.Count; IMessageProcessor[] blockServerProcs = new IMessageProcessor[bssz]; // Make the block server connections, for (int o = 0; o < bssz; ++o) { IServiceAddress address = blockServers[o].Address; blockServerProcs[o] = connector.Connect(address, ServiceType.Block); IEnumerable<Message> inputStream = blockServerProcs[o].Process(outputStream); ++NetworkCommCount; foreach (Message m in inputStream) { if (m.HasError) { // If this is an error, we need to report the failure to the // manager server, ReportBlockServerFailure(address); // Remove the block id from the server list cache, networkCache.RemoveServersWithBlock(blockId); // Rollback any server writes already successfully made, for (int p = 0; p < successProcess.Count; p += 2) { IServiceAddress blocksAddr = (IServiceAddress) successProcess[p]; MessageStream toRollback = (MessageStream) successProcess[p + 1]; List<DataAddress> rollbackNodes = new List<DataAddress>(128); foreach (Message rm in toRollback) { DataAddress raddr = (DataAddress) rm.Arguments[0].Value; rollbackNodes.Add(raddr); } // Create the rollback message, MessageStream rollbackMsg = new MessageStream(); rollbackMsg.AddMessage(new Message("rollbackNodes", new object[] {rollbackNodes.ToArray()})); // Send it to the block server, IEnumerable<Message> responseStream = connector.Connect(blocksAddr, ServiceType.Block).Process(rollbackMsg); ++NetworkCommCount; foreach (Message rbm in responseStream) { // If rollback generated an error we throw the error now // because this likely is a serious network error. if (rbm.HasError) { throw new NetworkWriteException("Write failed (rollback failed): " + rbm.ErrorMessage); } } } // Retry, if (tryCount > 0) return InternalPersist(sequence, tryCount - 1); // Otherwise we fail the write throw new NetworkWriteException(m.ErrorMessage); } } // If we succeeded without an error, add to the log successProcess.Add(address); successProcess.Add(outputStream); } } // Return the references, return outNodeIds; }
private DataAddress InternalGetPathNow(PathInfo pathInfo, IServiceAddress rootServer) { MessageStream outputStream = new MessageStream(); outputStream.AddMessage(new Message("getPathNow", pathInfo.PathName, pathInfo.VersionNumber)); Message m = ProcessSingleRoot(outputStream, rootServer); if (m.HasError) throw new ApplicationException(m.ErrorMessage); return (DataAddress) m.Arguments[0].Value; }
private IDictionary<BlockId, IList<BlockServerElement>> GetServerListForBlocks(List<BlockId> blockIds) { // The result map, Dictionary<BlockId, IList<BlockServerElement>> resultMap = new Dictionary<BlockId, IList<BlockServerElement>>(); List<BlockId> noneCached = new List<BlockId>(blockIds.Count); foreach (BlockId blockId in blockIds) { IList<BlockServerElement> v = networkCache.GetServersWithBlock(blockId); // If it's cached (and the cache is current), if (v != null) { resultMap.Add(blockId, v); } // If not cached, add to the list of none cached entries, else { noneCached.Add(blockId); } } // If there are no 'none_cached' blocks, if (noneCached.Count == 0) { // Return the result, return resultMap; } // Otherwise, we query the manager server for current records on the given // blocks. MessageStream outputStream = new MessageStream(); foreach (BlockId blockId in noneCached) { outputStream.AddMessage(new Message("getServerList", blockId)); } // Process a command on the manager, IEnumerable<Message> inputStream = ProcessManager(outputStream); int n = 0; foreach (Message m in inputStream) { if (m.HasError) throw new ApplicationException(m.ErrorMessage); int sz = (int) m.Arguments[0].Value; List<BlockServerElement> srvs = new List<BlockServerElement>(sz); for (int i = 0; i < sz; ++i) { IServiceAddress address = (IServiceAddress) m.Arguments[1 + (i*2)].Value; ServiceStatus status = (ServiceStatus) m.Arguments[1 + (i*2) + 1].Value; srvs.Add(new BlockServerElement(address, status)); } // Shuffle the list CollectionsUtil.Shuffle(srvs); // Move the server closest to this node to the start of the list, int closest = 0; int curCloseFactor = Int32.MaxValue; for (int i = 0; i < sz; ++i) { BlockServerElement elem = srvs[i]; int closenessFactor = FindClosenessToHere(elem.Address); if (closenessFactor < curCloseFactor) { curCloseFactor = closenessFactor; closest = i; } } // Swap if necessary, if (closest > 0) CollectionsUtil.Swap(srvs, 0, closest); // Put it in the result map, BlockId blockId = noneCached[n]; resultMap[blockId] = srvs; // Add it to the cache, // NOTE: TTL hard-coded to 15 minute networkCache.SetServersForBlock(blockId, srvs, 15*60*1000); ++n; } // Return the list return resultMap; }
private PathInfo GetPathInfoFor(string pathName) { PathInfo pathInfo = networkCache.GetPathInfo(pathName); if (pathInfo == null) { // Path info not found in the cache, so query the manager cluster for the // info. MessageStream outputStream = new MessageStream(); outputStream.AddMessage(new Message("getPathInfoForPath", pathName)); IEnumerable<Message> inputStream = ProcessManager(outputStream); foreach (Message m in inputStream) { if (m.HasError) { log.Error(String.Format("'getPathInfoFor' command failed: {0}", m.ErrorMessage)); log.Error(m.ErrorStackTrace); throw new ApplicationException(m.ErrorMessage); } pathInfo = (PathInfo) m.Arguments[0].Value; } if (pathInfo == null) throw new ApplicationException("Path not found: " + pathName); // Put it in the local cache, networkCache.SetPathInfo(pathName, pathInfo); } return pathInfo; }
internal String[] FindAllPaths() { MessageStream outputStream = new MessageStream(); outputStream.AddMessage(new Message("getAllPaths")); // Process a command on the manager, IEnumerable<Message> inputStream = ProcessManager(outputStream); foreach (Message m in inputStream) { if (m.HasError) { log.Error(String.Format("'getAllPaths' command failed: {0}", m.ErrorMessage)); log.Error(m.ErrorStackTrace); throw new ApplicationException(m.ErrorMessage); } return (String[]) m.Arguments[0].Value; } throw new ApplicationException("Bad formatted message stream"); }
public DataAddress PerformCommit(String pathName, DataAddress proposal) { // Get the PathInfo object for the given path name, PathInfo pathInfo = GetPathInfoFor(pathName); // We can only commit on the root leader, IServiceAddress rootServer = pathInfo.RootLeader; try { // TODO; If the root leader is not available, we need to go through // a new leader election process. MessageStream outputStream = new MessageStream(); outputStream.AddMessage(new Message("commit", pathName, pathInfo.VersionNumber, proposal)); Message m = ProcessSingleRoot(outputStream, rootServer); if (m.HasError) { // Rethrow commit fault locally, if (m.Error.Source.Equals("Deveel.Data.Net.CommitFaultException")) throw new CommitFaultException(m.ErrorMessage); throw new ApplicationException(m.ErrorMessage); } // Return the DataAddress of the result transaction, return (DataAddress) m.Arguments[0].Value; } catch (InvalidPathInfoException) { // Clear the cache and requery the manager server for a new path info, networkCache.SetPathInfo(pathName, null); return PerformCommit(pathName, proposal); } }
protected override IEnumerable<Message> Deserialize(BinaryReader reader) { int sz = reader.ReadInt32(); MessageStream stream = new MessageStream(); for (int i = 0; i < sz; i++) { stream.AddMessage(DeserializeMessage(reader)); } return stream; }
private void PollServer(TrackedService server) { bool pollOk = true; string commandArg = null; if (server.ServiceType == ServiceType.Block) commandArg = "heartbeatB"; else if (server.ServiceType == ServiceType.Root) commandArg = "heartbeatR"; else if (server.ServiceType == ServiceType.Manager) commandArg = "heartbeatM"; else { tracker.log.Error(String.Format("Don't know how to poll type {0}", server.ServiceType)); pollOk = false; } // Send the poll command to the server, IMessageProcessor p = connector.Connect(server.ServiceAddress, ServiceType.Block); MessageStream outputStream = new MessageStream(); outputStream.AddMessage(new Message("poll", commandArg)); IEnumerable<Message> inputStream = p.Process(outputStream); foreach (Message m in inputStream) { // Any error with the poll means no status change, if (m.HasError) { pollOk = false; } } // If the poll is ok, set the status of the server to UP and remove from // the monitor list, if (pollOk) { // The server status is set to 'STATUS_UP' if either the current state // is 'DOWN CLIENT REPORT' or 'DOWN HEARTBEAT' // Synchronize over 'servers_map' for safe alteration of the ref. ServiceStatus oldStatus; lock (monitoredServers) { oldStatus = server.CurrentStatus; if (oldStatus == ServiceStatus.DownClientReport || oldStatus == ServiceStatus.DownHeartbeat) { server.CurrentStatus = ServiceStatus.Up; } // Remove the server from the monitored_servers list. monitoredServers.Remove(server); } if (tracker.log.IsInterestedIn(LogLevel.Information)) { tracker.log.Info(String.Format("Poll ok. Status now UP for {0} {1}", server.ServiceAddress, server.ServiceType)); } // Fire the event if the status changed, try { if (tracker.StatusChange != null) tracker.StatusChange(this, new ServiceStatusEventArgs(server.ServiceAddress, server.ServiceType, oldStatus, ServiceStatus.Up)); } catch (Exception e) { // Catch any exception generated. Log it but don't terminate the // thread. tracker.log.Error("Exception in listener during poll", e); } } else { // Make sure the server status is set to 'DOWN HEARTBEAT' if the poll // failed, // Synchronize over 'servers_map' for safe alteration of the ref. lock (monitoredServers) { ServiceStatus sts = server.CurrentStatus; if (sts == ServiceStatus.Up || sts == ServiceStatus.DownClientReport) { server.CurrentStatus = ServiceStatus.DownHeartbeat; } } } }
private void InternalFetchLogBundle(MessageStream replyMessage, long[] uid, bool initial) { // Perform this under a lock. This lock is also active for block queries // and administration updates. lock (blockDbWriteLock) { // Create a transaction ITransaction transaction = blockDatabase.CreateTransaction(); try { // Create the UIDList object, IDataFile uidListDf = transaction.GetFile(UidListKey, FileAccess.ReadWrite); UidList uidList = new UidList(uidListDf); // Go to the position of the uid, long pos = 0; if (uid != null) { pos = uidList.PositionOfUid(uid); } long end = Math.Min(pos + 32, uidList.Count); if (pos < 0) { pos = -(pos + 1); } // If initial is true, we go back a bit if (initial) { // Go back 16 entries in the log (but don't go back before the first) pos = Math.Max(0, (pos - 16)); } else { // Go to the next entry, pos = pos + 1; } // Send the bundle out to the stream, for (long i = pos; i < end; ++i) { long[] inUid = uidList.GetUid(i); byte[] buf = GetValueFromUid(transaction, inUid); replyMessage.AddMessage(new Message(inUid, buf)); } } finally { blockDatabase.Dispose(transaction); } } }
public IEnumerable<Message> Process(IEnumerable<Message> stream) { // The reply message, MessageStream replyMessage = new MessageStream(); // The messages in the stream, foreach (Message m in stream) { try { // Check the server isn't in a stop state, service.CheckErrorState(); String cmd = m.Name; // getServerList(BlockId) if (cmd.Equals("getServerList")) { BlockServiceInfo[] servers = GetServerList((BlockId) m.Arguments[0].Value); Message response = new Message(); response.Arguments.Add(servers.Length); for (int i = 0; i < servers.Length; ++i) { response.Arguments.Add(servers[i].Address); response.Arguments.Add(service.serviceTracker.GetServiceCurrentStatus(servers[i].Address, ServiceType.Block)); } replyMessage.AddMessage(response); } // allocateNode(int node_size) else if (cmd.Equals("allocateNode")) { DataAddress address = AllocateNode((int) m.Arguments[0].Value); replyMessage.AddMessage(new Message(address)); } // registerBlockServer(ServiceAddress service_address) else if (cmd.Equals("registerBlockServer")) { service.RegisterBlockServer((IServiceAddress) m.Arguments[0].Value); replyMessage.AddMessage(new Message(1)); } // deregisterBlockServer(IServiceAddress) else if (cmd.Equals("deregisterBlockServer")) { service.DeregisterBlockServer((IServiceAddress) m.Arguments[0].Value); replyMessage.AddMessage(new Message(1)); } // deregisterAllBlockServers() else if (cmd.Equals("deregisterAllBlockServers")) { service.DeregisterAllBlockServers(); replyMessage.AddMessage(new Message(1)); } // registerManagerServers(ServiceAddress[] managers) else if (cmd.Equals("registerManagerServers")) { service.RegisterManagerServers((IServiceAddress[]) m.Arguments[0].Value); replyMessage.AddMessage(new Message(1)); } // deregisterAllManagerServers() else if (cmd.Equals("deregisterManagerServer")) { service.DeregisterManagerServer((IServiceAddress) m.Arguments[0].Value); replyMessage.AddMessage(new Message(1)); } // addPathToNetwork(string, string, IServiceAddress, IServiceAddress[]) else if (cmd.Equals("addPathToNetwork")) { service.AddPathToNetwork((string) m.Arguments[0].Value, (string) m.Arguments[1].Value, (IServiceAddress) m.Arguments[2].Value, (IServiceAddress[]) m.Arguments[3].Value); replyMessage.AddMessage(new Message(1)); } // removePathFromNetwork(String path_name) else if (cmd.Equals("removePathFromNetwork")) { service.RemovePathFromNetwork((string) m.Arguments[0].Value); replyMessage.AddMessage(new Message(1)); } // addBlockServerMapping(BlockId, long[]) else if (cmd.Equals("internalAddBlockServerMapping")) { service.InternalAddBlockServerMapping((BlockId) m.Arguments[0].Value, (long[]) m.Arguments[1].Value); replyMessage.AddMessage(new Message(1)); } // removeBlockServerMapping(BlockId, long[]) else if (cmd.Equals("internalRemoveBlockServerMapping")) { service.InternalRemoveBlockServerMapping((BlockId) m.Arguments[0].Value, (long[]) m.Arguments[1].Value); replyMessage.AddMessage(new Message(1)); } // --- Path processors --- // registerRootServer(IServiceAddress) else if (cmd.Equals("registerRootServer")) { service.RegisterRootServer((IServiceAddress) m.Arguments[0].Value); replyMessage.AddMessage(new Message(1)); } // deregisterRootServer(IServiceAddress) else if (cmd.Equals("deregisterRootServer")) { service.DeregisterRootServer((IServiceAddress) m.Arguments[0].Value); replyMessage.AddMessage(new Message(1)); } // deregisterAllConsensusProcessors() else if (cmd.Equals("deregisterAllRootServers")) { service.DeregisterAllRootServers(); replyMessage.AddMessage(new Message(1)); } // PathInfo getPathInfoForPath(string) else if (cmd.Equals("getPathInfoForPath")) { PathInfo pathInfo = service.GetPathInfoForPath((String) m.Arguments[0].Value); replyMessage.AddMessage(new Message(pathInfo)); } // string[] getAllPaths() else if (cmd.Equals("getAllPaths")) { string[] pathSet = service.GetAllPaths(); replyMessage.AddMessage(new Message(new object[] {pathSet})); } // getRegisteredServerList() else if (cmd.Equals("getRegisteredServerList")) { GetRegisteredServerList(replyMessage); } // getRegisteredBlockServers() else if (cmd.Equals("getRegisteredBlockServers")) { GetRegisteredBlockServers(replyMessage); } // getRegisteredRootServers() else if (cmd.Equals("getRegisteredRootServers")) { GetRegisteredRootServers(replyMessage); } // notifyBlockServerFailure(IServiceAddress) else if (cmd.Equals("notifyBlockServerFailure")) { service.NotifyBlockServerFailure((IServiceAddress) m.Arguments[0].Value); replyMessage.AddMessage(new Message(1)); } // notifyBlockIdCorruption(IServiceAddress, BlockId, string) else if (cmd.Equals("notifyBlockIdCorruption")) { service.NotifyBlockIdCorruption((IServiceAddress) m.Arguments[0].Value, (BlockId) m.Arguments[1].Value, (string) m.Arguments[2].Value); replyMessage.AddMessage(new Message(1)); } // getUniqueId() else if (cmd.Equals("getUniqueId")) { long uniqueId = service.managerUniqueId; replyMessage.AddMessage(new Message(uniqueId)); } // poll(String) else if (m.Name.Equals("poll")) { service.managerDb.CheckConnected(); replyMessage.AddMessage(new Message(1)); } else { // Defer to the manager db process command, service.managerDb.Process(m, replyMessage); } } catch (OutOfMemoryException e) { service.Logger.Error("Memory Error", e); service.SetErrorState(e); throw; } catch (Exception e) { service.Logger.Error("Exception during process", e); replyMessage.AddMessage(new Message(new MessageError(e))); } } return replyMessage; }
private void GetRegisteredBlockServers(MessageStream msg_out) { // Populate the list of registered block servers long[] guids; IServiceAddress[] srvs; lock (service.blockServersMap) { int sz = service.blockServersList.Count; guids = new long[sz]; srvs = new IServiceAddress[sz]; int i = 0; foreach (BlockServiceInfo m in service.blockServersList) { guids[i] = m.ServerGuid; srvs[i] = m.Address; ++i; } } // The reply message, msg_out.AddMessage(new Message(guids, srvs)); }
protected PathInfo LoadFromManagers(string pathName, int pathInfoVersion) { IServiceAddress[] manSrvs = managerServers; PathInfo pathInfo = null; bool foundOne = false; // Query all the available manager servers for the path info, for (int i = 0; i < manSrvs.Length && pathInfo == null; ++i) { IServiceAddress managerService = manSrvs[i]; if (serviceTracker.IsServiceUp(managerService, ServiceType.Manager)) { MessageStream outputStream = new MessageStream(); outputStream.AddMessage(new Message("getPathInfoForPath", pathName)); IMessageProcessor processor = connector.Connect(managerService, ServiceType.Manager); IEnumerable<Message> result = processor.Process(outputStream); Message lastM = null; foreach (Message m in result) { if (m.HasError) { if (!ReplicatedValueStore.IsConnectionFault(m)) // If it's not a connection fault, we rethrow the error, throw new ApplicationException(m.ErrorMessage); serviceTracker.ReportServiceDownClientReport(managerService, ServiceType.Manager); } else { lastM = m; foundOne = true; } } if (lastM != null) { pathInfo = (PathInfo)lastM.Arguments[0].Value; } } } // If not received a valid reply from a manager service, generate exception if (foundOne == false) throw new ServiceNotConnectedException("Managers not available"); // Create and return the path info object, return pathInfo; }
private void GetRegisteredRootServers(MessageStream outputStream) { // Populate the list of registered root servers IServiceAddress[] srvs; lock (service.rootServersList) { int sz = service.rootServersList.Count; srvs = new IServiceAddress[sz]; int i = 0; foreach (RootServiceInfo m in service.rootServersList) { srvs[i] = m.Address; ++i; } } // The reply message, outputStream.AddMessage(new Message(new object[] {srvs})); }
private void NotifyAllRootServersOfPost(PathInfo pathInfo, long uid, DataAddress rootNode) { // The root servers for the path, IServiceAddress[] roots = pathInfo.RootServers; // Create the message, MessageStream outputStream = new MessageStream(); outputStream.AddMessage(new Message("notifyNewProposal", pathInfo.PathName, uid, rootNode)); for (int i = 0; i < roots.Length; ++i) { IServiceAddress machine = roots[i]; // Don't notify this service, if (!machine.Equals(address)) { // If the service is up in the tracker, if (serviceTracker.IsServiceUp(machine, ServiceType.Root)) { // Send the message to the service, IMessageProcessor processor = connector.Connect(machine, ServiceType.Root); IEnumerable<Message> inputStream = processor.Process(outputStream); // If return is a connection fault, foreach (Message m in inputStream) { if (m.HasError && ReplicatedValueStore.IsConnectionFault(m)) { serviceTracker.ReportServiceDownClientReport(machine, ServiceType.Root); } } } } } }
private void GetRegisteredServerList(MessageStream outputStream) { // Populate the list of registered servers IServiceAddress[] srvs; ServiceStatus[] statusCodes; lock (service.blockServersMap) { int sz = service.blockServersList.Count; srvs = new IServiceAddress[sz]; statusCodes = new ServiceStatus[sz]; int i = 0; foreach (BlockServiceInfo m in service.blockServersList) { srvs[i] = m.Address; statusCodes[i] = service.serviceTracker.GetServiceCurrentStatus(m.Address, ServiceType.Block); ++i; } } // Populate the reply message, outputStream.AddMessage(new Message(srvs, statusCodes)); }
private bool SynchronizePathInfoData(PathAccess pathFile, IServiceAddress rootServer) { // Get the last entry, PathRecordEntry lastEntry = pathFile.GetLastEntry(); long uid; DataAddress daddr; if (lastEntry == null) { uid = 0; daddr = null; } else { uid = lastEntry.Uid; daddr = lastEntry.Address; } while (true) { // Fetch a bundle for the path from the root server, MessageStream outputStream = new MessageStream(); outputStream.AddMessage(new Message("internalFetchPathDataBundle", pathFile.PathName, uid, daddr)); // Send the command IMessageProcessor processor = connector.Connect(rootServer, ServiceType.Root); IEnumerable<Message> result = processor.Process(outputStream); long[] uids = null; DataAddress[] dataAddrs = null; foreach (Message m in result) { if (m.HasError) { // If it's a connection fault, report the error and return false if (ReplicatedValueStore.IsConnectionFault(m)) { serviceTracker.ReportServiceDownClientReport(rootServer, ServiceType.Root); return false; } throw new ApplicationException(m.ErrorMessage); } uids = (long[]) m.Arguments[0].Value; dataAddrs = (DataAddress[]) m.Arguments[1].Value; } // If it's empty, we reached the end so return, if (uids == null || uids.Length == 0) { break; } // Insert the data pathFile.AddPathDataEntries(uids, dataAddrs); // The last, uid = uids[uids.Length - 1]; daddr = dataAddrs[dataAddrs.Length - 1]; } return true; }
private void PollServer(TrackedService server) { bool pollOk = true; string commandArg = null; if (server.ServiceType == ServiceType.Block) { commandArg = "heartbeatB"; } else if (server.ServiceType == ServiceType.Root) { commandArg = "heartbeatR"; } else if (server.ServiceType == ServiceType.Manager) { commandArg = "heartbeatM"; } else { tracker.log.Error(String.Format("Don't know how to poll type {0}", server.ServiceType)); pollOk = false; } // Send the poll command to the server, IMessageProcessor p = connector.Connect(server.ServiceAddress, ServiceType.Block); MessageStream outputStream = new MessageStream(); outputStream.AddMessage(new Message("poll", commandArg)); IEnumerable <Message> inputStream = p.Process(outputStream); foreach (Message m in inputStream) { // Any error with the poll means no status change, if (m.HasError) { pollOk = false; } } // If the poll is ok, set the status of the server to UP and remove from // the monitor list, if (pollOk) { // The server status is set to 'STATUS_UP' if either the current state // is 'DOWN CLIENT REPORT' or 'DOWN HEARTBEAT' // Synchronize over 'servers_map' for safe alteration of the ref. ServiceStatus oldStatus; lock (monitoredServers) { oldStatus = server.CurrentStatus; if (oldStatus == ServiceStatus.DownClientReport || oldStatus == ServiceStatus.DownHeartbeat) { server.CurrentStatus = ServiceStatus.Up; } // Remove the server from the monitored_servers list. monitoredServers.Remove(server); } if (tracker.log.IsInterestedIn(LogLevel.Information)) { tracker.log.Info(String.Format("Poll ok. Status now UP for {0} {1}", server.ServiceAddress, server.ServiceType)); } // Fire the event if the status changed, try { if (tracker.StatusChange != null) { tracker.StatusChange(this, new ServiceStatusEventArgs(server.ServiceAddress, server.ServiceType, oldStatus, ServiceStatus.Up)); } } catch (Exception e) { // Catch any exception generated. Log it but don't terminate the // thread. tracker.log.Error("Exception in listener during poll", e); } } else { // Make sure the server status is set to 'DOWN HEARTBEAT' if the poll // failed, // Synchronize over 'servers_map' for safe alteration of the ref. lock (monitoredServers) { ServiceStatus sts = server.CurrentStatus; if (sts == ServiceStatus.Up || sts == ServiceStatus.DownClientReport) { server.CurrentStatus = ServiceStatus.DownHeartbeat; } } } }
private List<long> DoPersist(TreeWrite sequence, int tryCount) { // NOTE: nodes are written in order of branches and then leaf nodes. All // branch nodes and leafs are grouped together. // The list of nodes to be allocated, IList<ITreeNode> allBranches = sequence.BranchNodes; IList<ITreeNode> allLeafs = sequence.LeafNodes; List<ITreeNode> nodes = new List<ITreeNode>(allBranches.Count + allLeafs.Count); nodes.AddRange(allBranches); nodes.AddRange(allLeafs); int sz = nodes.Count; // The list of allocated referenced for the nodes, DataAddress[] refs = new DataAddress[sz]; long[] outRefs = new long[sz]; MessageStream allocateMessage = new MessageStream(MessageType.Request); // Make a connection with the manager server, IMessageProcessor manager = connector.Connect(managerAddress, ServiceType.Manager); // Allocate the space first, for (int i = 0; i < sz; ++i) { ITreeNode node = nodes[i]; RequestMessage request = new RequestMessage("allocateNode"); // Is it a branch node? if (node is TreeBranch) { // Branch nodes are 1K in size, request.Arguments.Add(1024); } else { // Leaf nodes are 4k in size, request.Arguments.Add(4096); } allocateMessage.AddMessage(request); } // The result of the set of allocations, MessageStream resultStream = (MessageStream) manager.Process(allocateMessage); //DEBUG: ++network_comm_count; // The unique list of blocks, List<long> uniqueBlocks = new List<long>(); // Parse the result stream one message at a time, the order will be the // order of the allocation messages, int n = 0; foreach (ResponseMessage m in resultStream) { if (m.HasError) throw m.Error.AsException(); DataAddress addr = (DataAddress) m.Arguments[0].Value; refs[n] = addr; // Make a list of unique block identifiers, if (!uniqueBlocks.Contains(addr.BlockId)) { uniqueBlocks.Add(addr.BlockId); } ++n; } // Get the block to server map for each of the blocks, IDictionary<long, IList<BlockServerElement>> blockToServerMap = GetServersForBlock(uniqueBlocks); // Make message streams for each unique block int ubid_count = uniqueBlocks.Count; MessageStream[] ubidStream = new MessageStream[ubid_count]; for (int i = 0; i < ubidStream.Length; ++i) { ubidStream[i] = new MessageStream(MessageType.Request); } // Scan all the blocks and create the message streams, for (int i = 0; i < sz; ++i) { byte[] nodeBuf; ITreeNode node = nodes[i]; // Is it a branch node? if (node is TreeBranch) { TreeBranch branch = (TreeBranch)node; // Make a copy of the branch (NOTE; we Clone() the array here). long[] curNodeData = (long[])branch.ChildPointers.Clone(); int curNdsz = branch.DataSize; branch = new TreeBranch(refs[i].Value, curNodeData, curNdsz); // The number of children int chsz = branch.ChildCount; // For each child, if it's a heap node, look up the child id and // reference map in the sequence and set the reference accordingly, for (int o = 0; o < chsz; ++o) { long childRef = branch.GetChild(o); if (childRef < 0) { // The ref is currently on the heap, so adjust accordingly int ref_id = sequence.LookupRef(i, o); branch.SetChildOverride(o, refs[ref_id].Value); } } // Turn the branch into a 'node_buf' byte[] array object for // serialization. long[] nodeData = branch.ChildPointers; int ndsz = branch.DataSize; MemoryStream bout = new MemoryStream(1024); BinaryWriter dout = new BinaryWriter(bout, Encoding.Unicode); dout.Write(BranchType); dout.Write(ndsz); for (int o = 0; o < ndsz; ++o) { dout.Write(nodeData[o]); } dout.Flush(); // Turn it into a byte array, nodeBuf = bout.ToArray(); // Put this branch into the local cache, networkCache.SetNode(refs[i], branch); } else { // If it's a leaf node, TreeLeaf leaf = (TreeLeaf)node; int lfsz = leaf.Length; nodeBuf = new byte[lfsz + 6]; // Technically, we could comment these next two lines out. ByteBuffer.WriteInt2(LeafType, nodeBuf, 0); ByteBuffer.WriteInt4(lfsz, nodeBuf, 2); leaf.Read(0, nodeBuf, 6, lfsz); // Put this leaf into the local cache, leaf = new ByteArrayTreeLeaf(refs[i].Value, nodeBuf); networkCache.SetNode(refs[i], leaf); } // The DataAddress this node is being written to, DataAddress address = refs[i]; // Get the block id, long blockId = address.BlockId; int bid = uniqueBlocks.IndexOf(blockId); RequestMessage request = new RequestMessage("writeToBlock"); request.Arguments.Add(address); request.Arguments.Add(nodeBuf); request.Arguments.Add(0); request.Arguments.Add(nodeBuf.Length); ubidStream[bid].AddMessage(request); // Update 'outRefs' array, outRefs[i] = refs[i].Value; } // A log of successfully processed operations, List<object> successProcess = new List<object>(64); // Now process the streams on the servers, for (int i = 0; i < ubidStream.Length; ++i) { // The output message, MessageStream requestMessageStream = ubidStream[i]; // Get the servers this message needs to be sent to, long block_id = uniqueBlocks[i]; IList<BlockServerElement> blockServers = blockToServerMap[block_id]; // Format a message for writing this node out, int bssz = blockServers.Count; IMessageProcessor[] blockServerProcs = new IMessageProcessor[bssz]; // Make the block server connections, for (int o = 0; o < bssz; ++o) { IServiceAddress address = blockServers[o].Address; blockServerProcs[o] = connector.Connect(address, ServiceType.Block); MessageStream responseMessageStream = (MessageStream) blockServerProcs[o].Process(requestMessageStream); //DEBUG: ++network_comm_count; if (responseMessageStream.HasError) { // If this is an error, we need to report the failure to the // manager server, ReportBlockServerFailure(address); // Remove the block id from the server list cache, networkCache.RemoveServers(block_id); // Rollback any server writes already successfully made, for (int p = 0; p < successProcess.Count; p += 2) { IServiceAddress blockAddress = (IServiceAddress) successProcess[p]; MessageStream toRollback = (MessageStream) successProcess[p + 1]; List<DataAddress> rollbackNodes = new List<DataAddress>(128); foreach(Message rm in toRollback) { DataAddress raddr = (DataAddress) rm.Arguments[0].Value; rollbackNodes.Add(raddr); } // Create the rollback message, RequestMessage rollbackRequest = new RequestMessage("rollbackNodes"); rollbackRequest.Arguments.Add(rollbackNodes.ToArray()); // Send it to the block server, Message responseMessage = connector.Connect(blockAddress, ServiceType.Block).Process(rollbackRequest); //DEBUG: ++network_comm_count; // If rollback generated an error we throw the error now // because this likely is a serious network error. if (responseMessage.HasError) throw new NetworkException("Rollback wrote failed: " + responseMessage.ErrorMessage); } // Retry, if (tryCount > 0) return DoPersist(sequence, tryCount - 1); // Otherwise we fail the write throw new NetworkException(responseMessageStream.ErrorMessage); } // If we succeeded without an error, add to the log successProcess.Add(address); successProcess.Add(requestMessageStream); } } // Return the references, return new List<long>(outRefs); }
public IEnumerable <Message> Process(IEnumerable <Message> stream) { // The map of containers touched, Dictionary <BlockId, BlockContainer> containersTouched = new Dictionary <BlockId, BlockContainer>(); // The reply message, MessageStream replyMessage = new MessageStream(); // The nodes fetched in this message, List <NodeId> readNodes = null; foreach (Message m in stream) { try { // Check for stop state, service.CheckErrorState(); // writeToBlock(DataAddress, byte[], int, int) if (m.Name.Equals("writeToBlock")) { WriteToBlock(containersTouched, (DataAddress)m.Arguments[0].Value, (byte[])m.Arguments[1].Value, (int)m.Arguments[2].Value, (int)m.Arguments[3].Value); replyMessage.AddMessage(new Message(1L)); } // readFromBlock(DataAddress) else if (m.Name.Equals("readFromBlock")) { if (readNodes == null) { readNodes = new List <NodeId>(); } DataAddress addr = (DataAddress)m.Arguments[0].Value; if (!readNodes.Contains(addr.Value)) { NodeSet nodeSet = ReadFromBlock(containersTouched, addr); replyMessage.AddMessage(new Message(nodeSet)); readNodes.AddRange(nodeSet.NodeIds); } } // rollbackNodes(DataAddress[] ) else if (m.Name.Equals("rollbackNodes")) { RemoveNodes(containersTouched, (DataAddress[])m.Arguments[0].Value); replyMessage.AddMessage(new Message(1L)); } // deleteBlock(BlockId) else if (m.Name.Equals("deleteBlock")) { DeleteBlock((BlockId)m.Arguments[0].Value); replyMessage.AddMessage(new Message(1L)); } // serverGUID() else if (m.Name.Equals("serverGUID")) { replyMessage.AddMessage(new Message(service.Id)); } // blockSetReport() else if (m.Name.Equals("blockSetReport")) { BlockId[] arr = BlockSetReport(); replyMessage.AddMessage(new Message(service.Id, arr)); } // poll(String) else if (m.Name.Equals("poll")) { replyMessage.AddMessage(new Message(1L)); } // notifyCurrentBlockId(BlockId) else if (m.Name.Equals("notifyCurrentBlockId")) { service.NotifyCurrentBlockId((BlockId)m.Arguments[0].Value); replyMessage.AddMessage(new Message(1L)); } // blockChecksum(BlockId) else if (m.Name.Equals("blockChecksum")) { long checksum = BlockChecksum(containersTouched, (BlockId)m.Arguments[0].Value); replyMessage.AddMessage(new Message(checksum)); } // sendBlockTo(BlockId, IServiceAddress, long, IServerAddress[]) else if (m.Name.Equals("sendBlockTo")) { // Returns immediately. There's currently no way to determine // when this process will happen or if it will happen. BlockId blockId = (BlockId)m.Arguments[0].Value; IServiceAddress destAddress = (IServiceAddress)m.Arguments[1].Value; long destServerId = (long)m.Arguments[2].Value; IServiceAddress[] managerServers = (IServiceAddress[])m.Arguments[3].Value; long processId = SendBlockTo(blockId, destAddress, destServerId, managerServers); replyMessage.AddMessage(new Message(processId)); } // sendBlockPart(BlockId, long, int, byte[], int) else if (m.Name.Equals("sendBlockPart")) { BlockId blockId = (BlockId)m.Arguments[0].Value; long pos = (long)m.Arguments[1].Value; int fileType = (int)m.Arguments[2].Value; byte[] buf = (byte[])m.Arguments[3].Value; int bufSize = (int)m.Arguments[4].Value; service.WriteBlockPart(blockId, pos, fileType, buf, bufSize); replyMessage.AddMessage(new Message(1L)); } // sendBlockComplete(BlockId, int) else if (m.Name.Equals("sendBlockComplete")) { BlockId blockId = (BlockId)m.Arguments[0].Value; int fileType = (int)m.Arguments[1].Value; service.WriteBlockComplete(blockId, fileType); replyMessage.AddMessage(new Message(1L)); } // createAvailabilityMapForBlocks(BlockId[]) else if (m.Name.Equals("createAvailabilityMapForBlocks")) { BlockId[] blockIds = (BlockId[])m.Arguments[0].Value; byte[] map = service.CreateAvailabilityMapForBlocks(blockIds); replyMessage.AddMessage(new Message(map)); } // bindWithManager() else if (m.Name.Equals("bindWithManager")) { BindWithManager(); replyMessage.AddMessage(new Message(1L)); } // unbindWithManager() else if (m.Name.Equals("unbindWithManager")) { UnbindWithManager(); replyMessage.AddMessage(new Message(1L)); } else { throw new ApplicationException("Unknown command: " + m.Name); } } catch (OutOfMemoryException e) { service.Logger.Error("Memory Error", e); service.SetErrorState(e); throw; } catch (Exception e) { service.Logger.Error("Exception during process", e); replyMessage.AddMessage(new Message(new MessageError(e))); } } // Release any containers touched, try { CloseContainers(containersTouched); } catch (IOException e) { service.Logger.Error("IOError when closing containers", e); } return(replyMessage); }
public MessageStream AsStream() { MessageStream stream = new MessageStream(); stream.AddMessage(this); return stream; }
public IEnumerable<Message> Process(IEnumerable<Message> request) { // The message output, MessageStream response = new MessageStream(); // For each message in the message input, foreach (Message m in request) { try { string command = m.Name; // Report on the services running, if (command.Equals("report")) { lock (service.serverManagerLock) { long tm = System.Diagnostics.Process.GetCurrentProcess().PrivateMemorySize64; long fm = 0 /* TODO: GetFreeMemory()*/; long td = 0 /* TODO: GetTotalSpace(service.basePath) */; long fd = 0 /* TODO: GetUsableSpace(service.basePath)*/; MachineRoles roles = MachineRoles.None; Message message = new Message(); if (service.block != null) roles |= MachineRoles.Block; if (service.manager != null) roles |= MachineRoles.Manager; if (service.root != null) roles |= MachineRoles.Root; message.Arguments.Add((byte) roles); message.Arguments.Add(tm - fm); message.Arguments.Add(tm); message.Arguments.Add(td - fd); message.Arguments.Add(td); response.AddMessage(message); } } else if (command.Equals("reportStats")) { // Analytics stats; we convert the stats to a long[] array and // send it as a reply. long[] stats = GetStats(); response.AddMessage(new Message(new object[] {stats})); } else { // Starts a service, if (command.Equals("start")) { ServiceType serviceType = (ServiceType)(byte) m.Arguments[0].Value; service.StartService(serviceType); } // Stops a service, else if (command.Equals("stop")) { ServiceType serviceType = (ServiceType)(byte) m.Arguments[0].Value; service.StopService(serviceType); } else { throw new ApplicationException("Unknown command: " + command); } // Add reply message, response.AddMessage(new Message(1L)); } } catch (OutOfMemoryException e) { service.Logger.Error("Out-Of-Memory", e); // This will end the connection throw; } catch (Exception e) { service.Logger.Error("Exception during process", e); response.AddMessage(new Message(new MessageError(e))); } } return response; }