/** * get the region with a int ip address with memory binary search algorithm * * @param ip * @throws IOException */ public DataBlock memorySearch(long ip) { int blen = IndexBlock.getIndexBlockLength(); if (dbBinStr == null) { dbBinStr = new byte[(int)raf.length()]; raf.seek(0L); raf.readFully(dbBinStr, 0, dbBinStr.Length); //initialize the global vars firstIndexPtr = Util.getIntLong(dbBinStr, 0); lastIndexPtr = Util.getIntLong(dbBinStr, 4); totalIndexBlocks = (int)((lastIndexPtr - firstIndexPtr) / blen) + 1; } //search the index blocks to define the data int l = 0, h = totalIndexBlocks; long sip, eip, dataptr = 0; while (l <= h) { int m = (l + h) >> 1; int p = (int)(firstIndexPtr + m * blen); sip = Util.getIntLong(dbBinStr, p); if (ip < sip) { h = m - 1; } else { eip = Util.getIntLong(dbBinStr, p + 4); if (ip > eip) { l = m + 1; } else { dataptr = Util.getIntLong(dbBinStr, p + 8); break; } } } //not matched if (dataptr == 0) { return(null); } //get the data int dataLen = (int)((dataptr >> 24) & 0xFF); int dataPtr = (int)((dataptr & 0x00FFFFFF)); int city_id = (int)Util.getIntLong(dbBinStr, dataPtr); //String region = new String(dbBinStr, dataPtr + 4, dataLen - 4, "UTF-8"); var region = ReadString(dbBinStr, dataPtr + 4, dataLen - 4); return(new DataBlock(city_id, region, dataPtr)); }
/** * initialize the db file * * @param raf * @throws IOException */ private void initDbFile(RandomAccessFile raf) { //1. zero fill the header part raf.seek(0L); raf.write(new byte[8]); //super block raf.write(new byte[dbConfig.getTotalHeaderSize()]); //header block headerPool = new List <HeaderBlock>(); //new LinkedList<HeaderBlock>(); indexPool = new List <IndexBlock>(); //new LinkedList<IndexBlock>(); }
/** * make the Db file * * @param dbFile target output file path * @throws IOException */ public void make(String dbFile) { //check and load the gloabl region if (globalRegionFile != null) { Console.WriteLine("+-Try to load the global region data ..."); StreamReader greader = new StreamReader((globalRegionFile)); String gline = null; while (!greader.EndOfStream) { gline = greader.ReadLine();// != null if (String.IsNullOrWhiteSpace(gline)) { continue; } String[] p = gline.Split(","); if (p.Length != 5) { continue; } //push the mapping globalRegionMap.put(p[2], Int32.Parse(p[0])); } greader.Close(); Console.WriteLine("|--[Ok]"); } //alloc the header size StreamReader reader = new StreamReader(this.ipSrcFile); RandomAccessFile raf = new RandomAccessFile(dbFile); //init the db file initDbFile(raf); Console.WriteLine("+-Db file initialized."); //analysis main loop Console.WriteLine("+-Try to write the data blocks ... "); String line = null; while (!reader.EndOfStream) { //line = reader.ReadLine() line = reader.ReadLine(); if (String.IsNullOrWhiteSpace(line)) { continue; } line = line.Trim(); if (line.Length == 0) { continue; } if (line[0] == '#') { continue; } //1. get the start ip int sIdx = 0, eIdx = 0; if ((eIdx = line.IndexOf('|', sIdx + 1)) == -1) { continue; } String startIp = line.Substring(sIdx, eIdx); //2. get the end ip sIdx = eIdx + 1; if ((eIdx = line.IndexOf('|', sIdx + 1)) == -1) { continue; } String endIp = line.Substring(sIdx, eIdx - sIdx); //3. get the region sIdx = eIdx + 1; String region = line.Substring(sIdx); Console.WriteLine("+-Try to process item " + line); addDataBlock(raf, startIp, endIp, region); Console.WriteLine("|--[Ok]"); } Console.WriteLine("|--Data block flushed!"); Console.WriteLine("|--Data file pointer: " + raf.getFilePointer() + "\n"); //write the index bytes Console.WriteLine("+-Try to write index blocks ... "); //record the start block IndexBlock indexBlock = null; HeaderBlock hb = null; indexBlock = indexPool.First(); long indexStartIp = indexBlock.getStartIp(), indexStratPtr = raf.getFilePointer(), indexEndPtr; headerPool.add(new HeaderBlock(indexStartIp, (int)(indexStratPtr))); int blockLength = IndexBlock.getIndexBlockLength(); int counter = 0, shotCounter = (dbConfig.getIndexBlockSize() / blockLength) - 1; //Iterator<IndexBlock> indexIt = indexPool.iterator(); //while ( indexIt.hasNext() ) { foreach (var block in indexPool) { if (++counter >= shotCounter) { hb = new HeaderBlock( block.getStartIp(), (int)raf.getFilePointer() ); headerPool.add(hb); counter = 0; } //write the buffer raf.write(block.getBytes()); } //record the end block if (counter > 0) { indexBlock = indexPool.Last(); hb = new HeaderBlock( indexBlock.getStartIp(), ((int)raf.getFilePointer()) - IndexBlock.getIndexBlockLength() ); headerPool.add(hb); } indexEndPtr = raf.getFilePointer(); Console.WriteLine("|--[Ok]"); //write the super blocks Console.WriteLine("+-Try to write the super blocks ... "); raf.seek(0L); //reset the file pointer byte[] superBuffer = new byte[8]; Util.writeIntLong(superBuffer, 0, indexStratPtr); Util.writeIntLong(superBuffer, 4, indexEndPtr - blockLength); raf.write(superBuffer); Console.WriteLine("|--[Ok]"); //write the header blocks Console.WriteLine("+-Try to write the header blocks ... "); //Iterator<HeaderBlock> headerIt = headerPool.iterator(); //while ( headerIt.hasNext() ) { // HeaderBlock headerBlock = headerIt.next(); // raf.write(headerBlock.getBytes()); //} foreach (var headerBlock in headerPool) { raf.write(headerBlock.getBytes()); } //write the copyright and the release timestamp info Console.WriteLine("+-Try to write the copyright and release date info ... "); raf.seek(raf.length()); //Calendar cal = Calendar.getInstance(); //SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd"); var date = DateTime.Now; String copyright = "Created by lionsoul at " + date.ToString("yyyy/MM/dd"); var timespan = new DateTimeOffset(date).ToUnixTimeSeconds(); raf.write((int)(timespan)); //the unix timestamp raf.write(copyright.getBytes("UTF-8")); Console.WriteLine("|--[Ok]"); reader.Close(); raf.close(); }