示例#1
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ChunkSplit"/> class.
 /// </summary>
 /// <param name="start1">The first chunk's start marker.</param>
 /// <param name="end1">The first chunk's end marker.</param>
 /// <param name="start2">The second chunk's start marker.</param>
 /// <param name="end2">The second chunk's end marker.</param>
 public ChunkSplit(ChunkMarker start1, ChunkMarker end1, ChunkMarker start2, ChunkMarker end2)
 {
     _start1 = start1;
     _end1   = end1;
     _start2 = start2;
     _end2   = end2;
 }
示例#2
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ChunkSplit"/> class.
 /// </summary>
 /// <param name="data">The data to read from.</param>
 /// <param name="index">The index at which to start reading from.</param>
 internal ChunkSplit(byte[] data, int index)
 {
     _start1 = ChunkMarker.ConvertFromString(ByteArrayHelper.ToString(data, ref index));
     _end1   = ChunkMarker.ConvertFromString(ByteArrayHelper.ToString(data, ref index));
     _start2 = ChunkMarker.ConvertFromString(ByteArrayHelper.ToString(data, ref index));
     _end2   = ChunkMarker.ConvertFromString(ByteArrayHelper.ToString(data, ref index));
 }
示例#3
0
        /// <summary>
        /// Initializes a new instance of the <see cref="ChunkTransfer"/> class.
        /// </summary>
        /// <param name="data">The data to read from.</param>
        /// <param name="index">The index at which to start reading from.</param>
        internal ChunkTransfer(byte[] data, int index)
        {
            string node = ByteArrayHelper.ToString(data, ref index);

            _node  = new NodeDefinition(node.Split(':')[0], int.Parse(node.Split(':')[1]));
            _start = ChunkMarker.ConvertFromString(ByteArrayHelper.ToString(data, ref index));
            _end   = ChunkMarker.ConvertFromString(ByteArrayHelper.ToString(data, ref index));
        }
示例#4
0
        /// <summary>
        /// Gets the chunk the specified id belongs in.
        /// </summary>
        /// <param name="id">The id to search for.</param>
        /// <returns>The chunk the specified id belongs in.</returns>
        private DatabaseChunk GetChunk(ObjectId id)
        {
            var value = _chunks.SingleOrDefault(e => ChunkMarker.IsBetween(e.Start, e.End, id.ToString()));

            if (value == null)
            {
                _lock.ExitReadLock();
                throw new ChunkMovedException();
            }

            return(value);
        }
示例#5
0
        /// <summary>
        /// Splits a chunk into two chunks.
        /// </summary>
        /// <returns>The new chunk created from the split.</returns>
        public DatabaseChunk Split()
        {
            var newData = new ConcurrentDictionary <ObjectId, Document>(_data.OrderBy(e => e.Key).Skip(_data.Count / 2).ToDictionary(e => e.Key, e => e.Value));

            _data = new ConcurrentDictionary <ObjectId, Document>(_data.OrderBy(e => e.Key).Take(_data.Count / 2));

            var oldEnd = _end;

            _end = new ChunkMarker(newData.Keys.Min().ToString());

            return(new DatabaseChunk(_end, oldEnd, newData));
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="ChunkListResponse"/> class.
        /// </summary>
        /// <param name="data">The data to read from.</param>
        /// <param name="index">The index at which to start reading from.</param>
        internal ChunkListResponse(byte[] data, int index)
        {
            _chunks = new List <ChunkDefinition>();
            string s = ByteArrayHelper.ToString(data, ref index);

            string[] defs = s.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
            foreach (var item in defs)
            {
                string[]       def     = item.Split(',');
                NodeDefinition nodeDef = new NodeDefinition(def[2].Split(':')[0], int.Parse(def[2].Split(':')[1]));
                _chunks.Add(new ChunkDefinition(ChunkMarker.ConvertFromString(def[0]), ChunkMarker.ConvertFromString(def[1]), nodeDef));
            }
        }
示例#7
0
        /// <summary>
        /// Gets a list of the chunks from the internal document.
        /// </summary>
        /// <returns>A list of the chunks from the internal document.</returns>
        private List <ChunkDefinition> GetList()
        {
            List <ChunkDefinition> returnValue = new List <ChunkDefinition>();

            for (int i = 0; i < _chunkList.Count; ++i)
            {
                var array = _chunkList[i.ToString()].ValueAsArray;
                var start = ChunkMarker.ConvertFromString(array[0].ValueAsString);
                var end   = ChunkMarker.ConvertFromString(array[1].ValueAsString);
                var node  = new NodeDefinition(array[2].ValueAsString.Split(':')[0], int.Parse(array[2].ValueAsString.Split(':')[1]));
                returnValue.Add(new ChunkDefinition(start, end, node));
            }

            return(returnValue);
        }
示例#8
0
        /// <summary>
        /// Merges this chunk with the one passed in.
        /// </summary>
        /// <param name="c">The chunk to merge.</param>
        /// <remarks>Make sure the chunks are sequential and that the chunk passed in comes after the current chunk.</remarks>
        public void Merge(DatabaseChunk c)
        {
            if (!Equals(_end, c._start))
            {
                throw new ArgumentException("The chunks are either not next to each other or you are trying to merge with the last chunk instead of the first.");
            }

            // Copy the data over.
            foreach (var item in c._data)
            {
                _data.TryAdd(item.Key, item.Value);
            }

            _end = c._end;
        }
示例#9
0
        /// <summary>
        /// Processes an update operation.
        /// </summary>
        /// <param name="dataOperation">The document that represents the operation.</param>
        /// <param name="message">The original message.</param>
        private void ProcessUpdateOperation(Document dataOperation, Message message)
        {
            UpdateOperation updateOperation = new UpdateOperation(dataOperation["update"].ValueAsDocument);

            if (!updateOperation.Valid)
            {
                SendMessage(new Message(message, updateOperation.ErrorMessage, false));
                return;
            }

            _chunkListLock.EnterReadLock();
            var chunk = _chunkList.SingleOrDefault(e => ChunkMarker.IsBetween(e.Start, e.End, updateOperation.DocumentId.ToString()));

            _chunkListLock.ExitReadLock();

            NodeDefinition node = chunk == null ? null : chunk.Node;

            if (node == null)
            {
                SendMessage(new Message(message, new DataOperationResult(ErrorCodes.FailedMessage, "No storage node up for the specified id range."), false));
                return;
            }

            Message operationMessage = new Message(node, message.Data, true);

            operationMessage.SetResponseCallback(delegate(Message originalOperationMessage)
            {
                if (originalOperationMessage.Success)
                {
                    DataOperationResult result = (DataOperationResult)originalOperationMessage.Response.Data;
                    Document resultDocument    = new Document(result.Result);
                    if (!resultDocument["success"].ValueAsBoolean && (ErrorCodes)Enum.Parse(typeof(ErrorCodes), resultDocument["errorcode"].ValueAsString) == ErrorCodes.ChunkMoved)
                    {
                        ProcessUpdateOperation(dataOperation, message);
                        return;
                    }

                    SendMessage(new Message(message, result, false));
                    return;
                }

                SendMessage(new Message(message, new DataOperationResult(ErrorCodes.FailedMessage, "Failed to send message to storage node."), false));
            });
            SendMessage(operationMessage);
        }
示例#10
0
        /// <summary>
        /// Processes a <see cref="ChunkDataResponse"/> message.
        /// </summary>
        /// <param name="start">The start of the chunk.</param>
        /// <param name="end">The end of the chunk.</param>
        /// <param name="data">The data that is contained in that chunk.</param>
        public void ProcessChunkDataResponse(ChunkMarker start, ChunkMarker end, Document data)
        {
            Stopwatch timer = new Stopwatch();

            timer.Start();
            DatabaseChunk chunk = new DatabaseChunk(start, end);

            for (int i = 0; i < data["count"].ValueAsInteger; ++i)
            {
                var doc = data[i.ToString()].ValueAsDocument;
                chunk.TryAdd(new ObjectId(doc["id"].ValueAsString), doc);
            }

            timer.Stop();

            _lock.EnterWriteLock();

            _chunks.Add(chunk);
            _chunks.Sort();

            _lock.ExitWriteLock();
            Logger.Log("Chunk data added in " + timer.Elapsed.TotalSeconds + " seconds.", LogLevel.Info);
        }
示例#11
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ChunkDataRequest"/> class.
 /// </summary>
 /// <param name="start">The start of the chunk.</param>
 /// <param name="end">The end of the chunk.</param>
 public ChunkDataRequest(ChunkMarker start, ChunkMarker end)
 {
     _start = start;
     _end   = end;
 }
示例#12
0
 /// <summary>
 /// Initializes a new instance of the <see cref="DatabaseChunk"/> class.
 /// </summary>
 /// <param name="start">The start of the chunk.</param>
 /// <param name="end">The end of the chunk.</param>
 /// <param name="data">The data to load the chunk with.</param>
 private DatabaseChunk(ChunkMarker start, ChunkMarker end, ConcurrentDictionary <ObjectId, Document> data)
 {
     _start = start;
     _end   = end;
     _data  = data;
 }
示例#13
0
 /// <summary>
 /// Initializes a new instance of the <see cref="DatabaseChunk"/> class.
 /// </summary>
 /// <param name="start">The start of the chunk.</param>
 /// <param name="end">The end of the chunk.</param>
 public DatabaseChunk(ChunkMarker start, ChunkMarker end)
 {
     _start = start;
     _end   = end;
 }
示例#14
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ChunkTransfer"/> class.
 /// </summary>
 /// <param name="node">The node the chunk is on.</param>
 /// <param name="start">The start of the chunk.</param>
 /// <param name="end">The end of the chunk.</param>
 public ChunkTransfer(NodeDefinition node, ChunkMarker start, ChunkMarker end)
 {
     _node  = node;
     _start = start;
     _end   = end;
 }
示例#15
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ChunkMerge"/> class.
 /// </summary>
 /// <param name="data">The data to read from.</param>
 /// <param name="index">The index at which to start reading from.</param>
 internal ChunkMerge(byte[] data, int index)
 {
     _start = ChunkMarker.ConvertFromString(ByteArrayHelper.ToString(data, ref index));
     _end   = ChunkMarker.ConvertFromString(ByteArrayHelper.ToString(data, ref index));
 }
示例#16
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ChunkMerge"/> class.
 /// </summary>
 /// <param name="start">The chunk's start marker.</param>
 /// <param name="end">The chunk's end marker.</param>
 public ChunkMerge(ChunkMarker start, ChunkMarker end)
 {
     _start = start;
     _end   = end;
 }
示例#17
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ChunkDefinition"/> class.
 /// </summary>
 /// <param name="start">The start of the chunk.</param>
 /// <param name="end">The end of the chunk.</param>
 /// <param name="node">The node the chunk is on.</param>
 public ChunkDefinition(ChunkMarker start, ChunkMarker end, NodeDefinition node)
 {
     _start = start;
     _end   = end;
     _node  = node;
 }