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.");
        }
Beispiel #2
0
        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;
        }
Beispiel #4
0
        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;
        }
Beispiel #5
0
        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;
        }
Beispiel #6
0
        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);
                        }
                    }
                }
            }
        }
Beispiel #7
0
            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;
            }
Beispiel #8
0
            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);
                }
            }
        }
Beispiel #19
0
            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;
            }
Beispiel #20
0
            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));
            }
Beispiel #21
0
        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;
        }
Beispiel #22
0
            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}));
            }
Beispiel #23
0
        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);
                            }
                        }
                    }
                }
            }
        }
Beispiel #24
0
            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));
            }
Beispiel #25
0
        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;
        }
Beispiel #26
0
            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;
                        }
                    }
                }
            }
Beispiel #27
0
        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);
        }
Beispiel #28
0
            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);
            }
Beispiel #29
0
 public MessageStream AsStream()
 {
     MessageStream stream = new MessageStream();
     stream.AddMessage(this);
     return stream;
 }
Beispiel #30
0
            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;
            }