/// <summary> /// Serializes all the tags in the given index. This serialization preserves the id's of each tag collection. /// </summary> /// <param name="stream">The target stream.</param> /// <param name="tagsIndex">The tags index to serialize.</param> public static void Serialize(Stream stream, ITagsCollectionIndex tagsIndex) { int begin = (int)stream.Position; // build a string index. ObjectTable <string> stringTable = new ObjectTable <string>(false); // convert tag collections to simpler objects. List <KeyValuePair <uint, List <KeyValuePair <uint, uint> > > > tagsIndexList = new List <KeyValuePair <uint, List <KeyValuePair <uint, uint> > > >(); for (uint tagId = 0; tagId < tagsIndex.Max; tagId++) { TagsCollection tagsCollection = tagsIndex.Get(tagId); if (tagsCollection != null) { // convert the tags collection to a list and add to the tag index. List <KeyValuePair <uint, uint> > tagsList = new List <KeyValuePair <uint, uint> >(); foreach (Tag tag in tagsCollection) { uint keyId = stringTable.Add(tag.Key); uint valueId = stringTable.Add(tag.Value); tagsList.Add(new KeyValuePair <uint, uint>( keyId, valueId)); } tagsIndexList.Add(new KeyValuePair <uint, List <KeyValuePair <uint, uint> > >(tagId, tagsList)); } } // do the serialization. TagIndexSerializer.Serialize(begin, stream, tagsIndexList, stringTable); // clear everything. tagsIndexList.Clear(); }
/// <summary> /// Serializes the tags into different indexed blocks of given size. /// </summary> /// <param name="stream"></param> /// <param name="tagsIndex"></param> /// <param name="blockSize"></param> public static void SerializeBlocks(Stream stream, ITagsIndexReadonly tagsIndex, uint blockSize) { int begin = (int)stream.Position; // calculate the amount of blocks. uint blocks = (uint)System.Math.Ceiling((float)tagsIndex.Max / (float)blockSize); // store block count. stream.Write(BitConverter.GetBytes((int)blocks), 0, 4); // store block size. stream.Write(BitConverter.GetBytes((int)blockSize), 0, 4); // move the stream to make room for the index. stream.Seek((blocks + 2) * 4 + begin, SeekOrigin.Begin); int beginBlocks = (int)stream.Position; // keep looping over these blocks. int[] blockPositions = new int[blocks]; for (uint blockIdx = 0; blockIdx < blocks; blockIdx++) { uint from = blockIdx * blockSize; uint to = from + blockSize; TagIndexSerializer.Serialize(stream, tagsIndex, from, to); blockPositions[blockIdx] = (int)stream.Position - beginBlocks; } // write the block positions. stream.Seek(begin + 8, SeekOrigin.Begin); for (int blockIdx = 0; blockIdx < blocks; blockIdx++) { stream.Write(BitConverter.GetBytes(blockPositions[blockIdx]), 0, 4); } }
/// <summary> /// Serializes the tags into different indexed blocks of given size. /// </summary> /// <param name="stream"></param> /// <param name="tagsIndex"></param> /// <param name="blockSize"></param> public static void SerializeBlocks(Stream stream, ITagsCollectionIndexReadonly tagsIndex, uint blockSize) { int begin = (int)stream.Position; // calculate the amount of blocks. uint blocks = (uint)System.Math.Ceiling((float)tagsIndex.Max / (float)blockSize); // store block count. stream.Write(BitConverter.GetBytes((int)blocks), 0, 4); // store block size. stream.Write(BitConverter.GetBytes((int)blockSize), 0, 4); // move the stream to make room for the index. stream.Seek((blocks + 2) * 4 + begin, SeekOrigin.Begin); int beginBlocks = (int)stream.Position; // keep looping over these blocks. int[] blockPositions = new int[blocks]; for (uint blockIdx = 0; blockIdx < blocks; blockIdx++) { uint from = blockIdx * blockSize; uint to = from + blockSize; MemoryStream memoryStream = new MemoryStream(); TagIndexSerializer.Serialize(memoryStream, tagsIndex, from, to); byte[] compressed = Ionic.Zlib.GZipStream.CompressBuffer(memoryStream.ToArray()); memoryStream.Dispose(); stream.Write(compressed, 0, compressed.Length); blockPositions[blockIdx] = (int)stream.Position - beginBlocks; } // write the block positions. stream.Seek(begin + 8, SeekOrigin.Begin); for (int blockIdx = 0; blockIdx < blocks; blockIdx++) { stream.Write(BitConverter.GetBytes(blockPositions[blockIdx]), 0, 4); } }