/** * Copyright (c) 2002-2013 "Neo Technology," * Network Engine for Objects in Lund AB [http://neotechnology.com] * * This file is part of Neo4j. * * Neo4j is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.neo4j.kernel.impl.storemigration.legacystore; import java.io.IOException; import java.nio.ByteBuffer; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import org.neo4j.kernel.impl.nioneo.store.InvalidRecordException; import org.neo4j.kernel.impl.nioneo.store.PropertyType; import org.neo4j.kernel.impl.nioneo.store.Record; public class LegacyDynamicRecordFetcher { private LegacyDynamicStoreReader stringPropertyStore; private LegacyDynamicStoreReader arrayPropertyStore; public LegacyDynamicRecordFetcher( String stringStoreFileName, String arrayStoreFileName ) throws IOException { stringPropertyStore = new LegacyDynamicStoreReader( stringStoreFileName, LegacyDynamicStoreReader.FROM_VERSION_STRING ); arrayPropertyStore = new LegacyDynamicStoreReader( arrayStoreFileName, LegacyDynamicStoreReader.FROM_VERSION_ARRAY ); } public List<LegacyDynamicRecord> readDynamicRecords( LegacyPropertyRecord record ) { if ( record.getType() == LegacyPropertyType.STRING ) { List<LegacyDynamicRecord> stringRecords = stringPropertyStore.getPropertyChain( record.getPropBlock() ); for ( LegacyDynamicRecord stringRecord : stringRecords ) { stringRecord.setType( PropertyType.STRING.intValue() ); } return stringRecords; } else if ( record.getType() == LegacyPropertyType.ARRAY ) { List<LegacyDynamicRecord> arrayRecords = arrayPropertyStore.getPropertyChain( record.getPropBlock() ); for ( LegacyDynamicRecord arrayRecord : arrayRecords ) { arrayRecord.setType( PropertyType.ARRAY.intValue() ); } return arrayRecords; } return null; } public Object getStringFor( LegacyPropertyRecord propRecord ) { long startRecordId = propRecord.getPropBlock(); List<LegacyDynamicRecord> legacyDynamicRecords = readDynamicRecords( propRecord ); return joinRecordsIntoString( startRecordId, legacyDynamicRecords ); } public static String joinRecordsIntoString( long startRecordId, List<LegacyDynamicRecord> legacyDynamicRecords ) { Map<Long, LegacyDynamicRecord> recordsMap = new HashMap<Long, LegacyDynamicRecord>(); long recordToFind = startRecordId; for ( LegacyDynamicRecord record : legacyDynamicRecords ) { recordsMap.put( record.getId(), record ); } List<char[]> charList = new LinkedList<char[]>(); while ( recordToFind != Record.NO_NEXT_BLOCK.intValue() ) { LegacyDynamicRecord record = recordsMap.get( recordToFind ); if ( !record.isCharData() ) { ByteBuffer buf = ByteBuffer.wrap( record.getData() ); char[] chars = new char[record.getData().length / 2]; buf.asCharBuffer().get( chars ); charList.add( chars ); } else { charList.add( record.getDataAsChar() ); } recordToFind = record.getNextBlock(); } StringBuffer buf = new StringBuffer(); for ( char[] str : charList ) { buf.append( str ); } return buf.toString(); } public Object getArrayFor( LegacyPropertyRecord propertyRecord ) { long recordToFind = propertyRecord.getPropBlock(); Map<Long, LegacyDynamicRecord> recordsMap = new HashMap<Long, LegacyDynamicRecord>(); for ( LegacyDynamicRecord record : readDynamicRecords( propertyRecord ) ) { recordsMap.put( record.getId(), record ); } List<byte[]> byteList = new LinkedList<byte[]>(); int totalSize = 0; while ( recordToFind != Record.NO_NEXT_BLOCK.intValue() ) { LegacyDynamicRecord record = recordsMap.get( recordToFind ); if ( !record.isCharData() ) { ByteBuffer buf = ByteBuffer.wrap( record.getData() ); byte[] bytes = new byte[record.getData().length]; totalSize += bytes.length; buf.get( bytes ); byteList.add( bytes ); } else { throw new InvalidRecordException( "Expected byte data on record " + record ); } recordToFind = record.getNextBlock(); } byte[] bArray = new byte[totalSize]; int offset = 0; for ( byte[] currentArray : byteList ) { System.arraycopy( currentArray, 0, bArray, offset, currentArray.length ); offset += currentArray.length; } return arrayPropertyStore.getRightArray( bArray ); } public void close() throws IOException { arrayPropertyStore.close(); stringPropertyStore.close(); } }