All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.bigdata.rdf.lexicon.TestBlobsIndex Maven / Gradle / Ivy

There is a newer version: 2.1.4
Show newest version
/**

 Copyright (C) SYSTAP, LLC DBA Blazegraph 2006-2016.  All rights reserved.

 Contact:
 SYSTAP, LLC DBA Blazegraph
 2501 Calvert ST NW #106
 Washington, DC 20008
 [email protected]

 This program 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; version 2 of the License.

 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, write to the Free Software
 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
/*
 * Created on Jun 6, 2011
 */
package com.bigdata.rdf.lexicon;

import java.util.Arrays;
import java.util.UUID;

import junit.framework.TestCase2;

import org.openrdf.model.vocabulary.XMLSchema;

import com.bigdata.btree.BTree;
import com.bigdata.btree.IndexMetadata;
import com.bigdata.btree.keys.IKeyBuilder;
import com.bigdata.btree.keys.KVO;
import com.bigdata.btree.keys.KeyBuilder;
import com.bigdata.io.SerializerUtil;
import com.bigdata.rawstore.IRawStore;
import com.bigdata.rawstore.SimpleMemoryRawStore;
import com.bigdata.rdf.internal.IV;
import com.bigdata.rdf.internal.IVUtility;
import com.bigdata.rdf.internal.VTE;
import com.bigdata.rdf.internal.impl.AbstractIV;
import com.bigdata.rdf.internal.impl.BlobIV;
import com.bigdata.rdf.lexicon.BlobsWriteTask.BlobsWriteProcResultHandler;
import com.bigdata.rdf.model.BigdataBNode;
import com.bigdata.rdf.model.BigdataLiteral;
import com.bigdata.rdf.model.BigdataURI;
import com.bigdata.rdf.model.BigdataValue;
import com.bigdata.rdf.model.BigdataValueFactory;
import com.bigdata.rdf.model.BigdataValueFactoryImpl;
import com.bigdata.rdf.util.DumpLexicon;
import com.bigdata.util.BytesUtil;

/**
 * Test suite for low-level operations on the BLOBS index.
 * 
 * @author thompsonbry
 */
public class TestBlobsIndex extends TestCase2 {

	public TestBlobsIndex() {
	}

	public TestBlobsIndex(final String name) {
		super(name);
	}

	/**
	 * Unit test for generation of sort keys from {@link BigdataValue}s to be
	 * represented as {@link BlobIV}s.
	 */
	public void test_generateSortKeys() {
		
		final BlobsIndexHelper h = new BlobsIndexHelper();
		
		final String namespace = getName();

		final BigdataValueFactory vf = BigdataValueFactoryImpl
				.getInstance(namespace);

		/*
		 * Generate Values that we will use to read and write on the TERMS
		 * index.
		 */
		final BigdataValue[] values;
		{
		
			final BigdataURI uri1 = vf
					.createURI("http://www.bigdata.com/testTerm");

			final BigdataLiteral lit1 = vf.createLiteral("bigdata");

			final BigdataLiteral lit2 = vf.createLiteral("bigdata", "en");

			final BigdataLiteral lit3 = vf.createLiteral("bigdata",
					XMLSchema.STRING);

			final BigdataBNode bnode1 = vf.createBNode();

			final BigdataBNode bnode2 = vf.createBNode("abc");

			values = new BigdataValue[] { 
					uri1, 
					lit1,
					lit2, 
					lit3, 
					bnode1, 
					bnode2 
					};

		}

		// Generate the sort keys.
		final KVO[] a = h.generateKVOs(vf
				.getValueSerializer(), values, values.length);

		/*
		 * Verify that we can decode fully formed TermIVs based on these prefix
		 * keys.
		 */
		{
			
			final IKeyBuilder keyBuilder = h.newKeyBuilder();

			for (int i = 0; i < a.length; i++) {

				final KVO kvo = a[i];
				
				final byte[] baseKey = kvo.key;

				final int counter = i;
				
				// A fully formed key.
				final byte[] key = h.makeKey(keyBuilder.reset(), baseKey,
						counter);

				// Wrap as a TermId,
				final BlobIV iv = (BlobIV) IVUtility.decodeFromOffset(
						key, 0/* offset */);
				//new TermId(key);

				// Verify 1st byte decodes to the VTE of the Value.
				assertEquals(VTE.valueOf(kvo.obj), AbstractIV.getVTE(KeyBuilder
						.decodeByte(key[0])));

				// Verify the the VTE encoding is consistent in the other
				// direction as well.
				assertEquals(BlobIV.toFlags(VTE.valueOf(kvo.obj)), KeyBuilder
						.decodeByte(key[0]));

				// Verify VTE was correctly encoded.
				assertEquals(VTE.valueOf(kvo.obj), iv.getVTE());

				// Verify hash code was correctly encoded.
				assertEquals(kvo.obj.hashCode(), iv.hashCode());
				
				// Verify we can decode the String value of the TermIV.
				assertEquals(iv, BlobIV.fromString(iv.toString()));
				
			}

		}

	}
	
//	/**
//	 * Unit test for creating the TERMS index.
//	 */
//	public void test_termsIndex_create() {
//
//		final IRawStore store = new SimpleMemoryRawStore();
//		
//		try {
//			
//		    final String namespace = getName();
//		    
//			final BTree ndx = createTermsIndex(store, namespace);
//
////			final TermsIndexHelper h = new TermsIndexHelper();
////			
////			final IKeyBuilder keyBuilder = h.newKeyBuilder();
////			
////	        for (VTE vte : VTE.values()) {
////	            
////                // Each VTE has an associated NullIV (mapped to a [null]).
////                assertNull(ndx.lookup(BlobIV.mockIV(vte).encode(
////                        keyBuilder.reset()).getKey()));
////	            
////	        }
////			
////            // Should be one entry for each type of NullIV.
////            assertEquals(4L, ndx.rangeCount());
////
////            // Verify we visit each of those NullIVs.
////	        final ITupleIterator itr = ndx.rangeIterator();
////
////	        while(itr.hasNext()) {
////	            
////	            final ITuple tuple = itr.next();
////	            
////	            assertTrue(tuple.isNull());
////	            
////	            // The tuple is deserialized as a [null] reference.
////                assertNull(tuple.getObject());
////
////	        }
//	        
//		} finally {
//			
//			store.destroy();
//			
//		}
//		
//	}

    /**
     * Return the {@link IndexMetadata} for the TERMS index.
     * 
     * @param name
     *            The name of the index.
     *            
     * @return The {@link IndexMetadata}.
     */
	static IndexMetadata getTermsIndexMetadata(final String namespace) {
	    
        final String name = namespace + ".TERMS";

        final BigdataValueFactory valueFactory = BigdataValueFactoryImpl
                .getInstance(namespace);
        
        final IndexMetadata metadata = new IndexMetadata(name, UUID
                .randomUUID());

//      final int m = 1024;
//      final int q = 8000;
//      final int ratio = 32;
//        final int maxRecLen = 0;

//      metadata.setNodeKeySerializer(new FrontCodedRabaCoder(ratio));

//      final DefaultTupleSerializer tupleSer = new DefaultTupleSerializer(
//              new DefaultKeyBuilderFactory(new Properties()),//
//              new FrontCodedRabaCoder(ratio),//
//              CanonicalHuffmanRabaCoder.INSTANCE
//      );
//
//      metadata.setTupleSerializer(tupleSer);

        // enable raw record support.
        metadata.setRawRecords(true);

//        // set the maximum length of a byte[] value in a leaf.
//        metadata.setMaxRecLen(maxRecLen);

//      /*
//       * increase the branching factor since leaf size is smaller w/o large
//       * records.
//       */
//      metadata.setBranchingFactor(m);
//
//      // Note: You need to give sufficient heap for this option!
//      metadata.setWriteRetentionQueueCapacity(q);

        metadata.setTupleSerializer(new BlobsTupleSerializer(namespace,
                valueFactory));

        return metadata;

	}

    /**
     * Create a TERMS index.
     * 
     * @param namespace
     *            The namespace of the TERMS index (e.g., for "kb.lex" the fully
     *            qualified name of the index would be "kb.lex.TERMS").
     * 
     * @return The terms index.
     */
	static BTree createTermsIndex(final IRawStore store, final String namespace) {

        final IndexMetadata metadata = getTermsIndexMetadata(namespace);

        final BTree ndx = BTree.create(store, metadata);

//        /*
//         * Insert a tuple for each kind of VTE having a ZERO hash code and a
//         * ZERO counter and thus qualifying it as a NullIV. Each of these tuples
//         * is mapped to a null value in the index. This reserves the possible
//         * distinct NullIV keys so they can not be assigned to real Values.
//         * 
//         * Note: The hashCode of "" is ZERO, so an empty Literal would otherwise
//         * be assigned the same key as mockIV(VTE.LITERAL).
//         */
//
//        final IKeyBuilder keyBuilder = new TermsIndexHelper().newKeyBuilder();
//
//        final byte[][] keys = new byte[][] {
//            BlobIV.mockIV(VTE.URI).encode(keyBuilder.reset()).getKey(), //
//            BlobIV.mockIV(VTE.BNODE).encode(keyBuilder.reset()).getKey(), //
//            BlobIV.mockIV(VTE.LITERAL).encode(keyBuilder.reset()).getKey(), //
//            BlobIV.mockIV(VTE.STATEMENT).encode(keyBuilder.reset()).getKey(), //
//        };
//        final byte[][] vals = new byte[][] { null, null, null, null };
//        
//        // submit the task and wait for it to complete.
//        ndx.submit(0/* fromIndex */, keys.length/* toIndex */, keys, vals,
//                BatchInsertConstructor.RETURN_NO_VALUES, null/* aggregator */);

        return ndx;

    }
	
	/**
	 * Unit test for lookup and adding values to the TERMS index when blank
	 * nodes are NOT stored in the TERMS index.
	 */
	public void test_termsIndex_addLookupValues_with_standard_bnode_semantics() {

		doTermsIndexAddLookupTest(false/* toldBNodes */);

	}

	/**
	 * Unit test for lookup and adding values to the TERMS index when blank
	 * nodes are stored in the TERMS index (told bnodes semantics).
	 */
	public void test_termsIndex_addLookupValue_with_toldBNodesMode() {

		doTermsIndexAddLookupTest(true/* toldBNodes */);

	}

	/**
	 * Test helper exercises the basic operations on the TERMS index, including
	 * (a) scanning a collision buckets to resolve {@link BigdataValue}s from
	 * their prefix keys; (b) adding a {@link BigdataValue}s to the TERMS index;
	 * and (c) point lookups using an {@link IV} as a fully qualified key for
	 * the TERMS index.
	 * 
	 * @param toldBNodes
	 *            when true blank nodes will be inserted into the
	 *            TERMS index.
	 */
	private void doTermsIndexAddLookupTest(final boolean toldBNodes) {
		
		final IRawStore store = new SimpleMemoryRawStore();
		
		try {
			
		    final String namespace = getName();
		    
			final BTree ndx = createTermsIndex(store, namespace);

			final BigdataValueFactory vf = BigdataValueFactoryImpl
					.getInstance(namespace);
			
			final BlobsIndexHelper h = new BlobsIndexHelper();

			/*
			 * Generate Values that we will use to read and write on the TERMS
			 * index.
			 */
			final BigdataValue[] values;
			{
			
				final BigdataURI uri1 = vf
						.createURI("http://www.bigdata.com/testTerm");

                // Note: These three literals wind up with the same hash code.
                // The hash code of the literal is based only on its label.
				final BigdataLiteral lit1 = vf.createLiteral("bigdata");

				final BigdataLiteral lit2 = vf.createLiteral("bigdata", "en");

				final BigdataLiteral lit3 = vf.createLiteral("bigdata",
						XMLSchema.STRING);

				final BigdataBNode bnode1 = vf.createBNode();

				final BigdataBNode bnode2 = vf.createBNode("abc");

				values = new BigdataValue[] { 
						uri1, 
						lit1,
						lit2, 
						lit3, 
						bnode1, 
						bnode2 
						};

			}

			final KVO[] a = h.generateKVOs(vf
					.getValueSerializer(), values, values.length);

			final byte[][] keys = new byte[a.length][];
			final byte[][] vals = new byte[a.length][];
			for (int i = 0; i < a.length; i++) {
				keys[i] = a[i].key;
				vals[i] = a[i].val;
			}
			
			// First, verify that the Value(s) were not found in the index.
			{
				final boolean readOnly = true;
				final WriteTaskStats stats = new WriteTaskStats();

				final BlobsWriteProc.BlobsWriteProcConstructor ctor = new BlobsWriteProc.BlobsWriteProcConstructor(
						readOnly, toldBNodes);

				ndx.submit(0/* fromIndex */, values.length/* toIndex */, keys,
						vals, ctor, new BlobsWriteProcResultHandler(a,
								readOnly, stats));

				for (int i = 0; i < a.length; i++) {
					
					// IV was not assigned (read-only and does not pre-exist).
					assertNull(a[i].obj.getIV());
					
				}

				assertEquals(a.length, stats.nunknown.get());
				
			}

			// Now, verify the IVs are assigned on insert.
			{

				final boolean readOnly = false;
				final WriteTaskStats stats = new WriteTaskStats();

				final BlobsWriteProc.BlobsWriteProcConstructor ctor = new BlobsWriteProc.BlobsWriteProcConstructor(
						readOnly, toldBNodes);

				ndx.submit(0/* fromIndex */, values.length/* toIndex */, keys,
						vals, ctor, new BlobsWriteProcResultHandler(a,
								readOnly, stats));

				// Note: [nunknown] is only set on read.
				assertEquals(0, stats.nunknown.get());

				/*
				 * Verify that the IV is a fully qualified key for the TERMS
				 * index.
				 */
				final IKeyBuilder keyBuilder = h.newKeyBuilder();
				
				for (int i = 0; i < a.length; i++) {

					final BigdataValue expected = a[i].obj;
					
					final IV iv = expected.getIV();

					// An IV was assigned to the BigdataValue.
					assertNotNull(iv);
					
					// Verify the VTE is consistent.
					assertEquals(VTE.valueOf(expected), iv.getVTE());

					// Verify the hash code is consistent.
					assertEquals(expected.hashCode(), iv.hashCode());

					// Encode the IV as a key.
					final byte[] key = iv.encode(keyBuilder.reset()).getKey();
					
					// Verify can encode/decode the IV.
					{
						
						final IV decodedIV = IVUtility.decode(key);
						
						assertEquals(iv, decodedIV);
						
					}
					
					// Point lookup using the IV as the key.
					final byte[] val = ndx.lookup(key);

					// Verify point lookup succeeds.
					if (val == null) {
						fail("Could not resolve IV against index: expectedIV="
								+ iv + ", key=" + BytesUtil.toString(key));
					}

					// Decode the returned byte[] as a Value.
					final BigdataValue actual = vf.getValueSerializer()
							.deserialize(val);
				
					// Verify BigdataValues are equal()
					if (!expected.equals(actual)) {
					
						log.error(DumpLexicon.dumpBlobs(namespace, ndx));
						
						fail("Expected=" + expected + "(" + iv + "), actual="
								+ actual + "(" + actual.getIV() + ")");
					}
					
					if (log.isInfoEnabled())
						log.info("i=" + expected + ", iv=" + iv);

				}

			}

			// Finally, verify that the assigned IVs are discovered on lookup.
			{

				/*
				 * Setup an array of the expected IVs and clear out the old IVs
				 * on the BigdataValue objects.
				 * 
				 * Note: Since we can not clear the IV once it has been set, this
				 * replaces the BigdataValues in the array with new values having
				 * the same data.
				 */
				final IV[] expected = new IV[a.length];
				final BigdataValueFactory vf2 = BigdataValueFactoryImpl
						.getInstance(namespace + "-not-the-same");
				for (int i = 0; i < a.length; i++) {
					final BigdataValue tmp = a[i].obj;
					assertNotNull(a[i].obj.getIV()); // IV is known (from above)
					expected[i] = a[i].obj.getIV(); // make a note of it.
					final BigdataValue newVal = vf.asValue(vf2.asValue(tmp));
					// replace entry in a[].
					a[i] = new KVO(a[i].key, a[i].val, newVal);
					assertEquals(tmp, a[i].obj);// same Value.
					assertNull(a[i].obj.getIV()); // but IV is not set.
				}

				final boolean readOnly = true;
				final WriteTaskStats stats = new WriteTaskStats();

				final BlobsWriteProc.BlobsWriteProcConstructor ctor = new BlobsWriteProc.BlobsWriteProcConstructor(
						readOnly, toldBNodes);

				ndx.submit(0/* fromIndex */, values.length/* toIndex */, keys,
						vals, ctor, new BlobsWriteProcResultHandler(a,
								readOnly, stats));

				int nnotfound = 0;
				for (int i = 0; i < a.length; i++) {

				    final IV expectedIV = expected[i];
				    
					final IV actualIV = a[i].obj.getIV();
					
					if(expectedIV.isBNode()) {
                        if (toldBNodes) {
                            // IV is discoverable.
                            assertNotNull(actualIV);
                            assertEquals(expected[i], actualIV);
                        } else {
                            // IV is NOT discoverable (can not unify bnodes).
							if (actualIV != null)
								fail("Not expecting to unify blank node: expectedIV="
										+ expectedIV
										+ ", but actualIV="
										+ actualIV + "(should be null)");
                            nnotfound++;
                        }
                    } else {
                        // IV is discoverable.
                        assertNotNull(actualIV);
                        assertEquals(expected[i], actualIV);
                    }
					
				}
				
				assertEquals(nnotfound, stats.nunknown.get());
				
			}

		} finally {
			
			store.destroy();
			
		}
		
	}

    /**
     * Unit test with standard blank nodes semantics verifies that separate
     * writes on the TERMS index using the same BNode ID result in distinct keys
     * being assigned (blank nodes do not unify).
     */
    public void test_blank_nodes_are_distinct() {

        final boolean storeBlankNodes = false;

        final IRawStore store = new SimpleMemoryRawStore();

        try {

            final String namespace = getName();
            
            final IndexMetadata metadata = getTermsIndexMetadata(namespace);

            final BTree ndx = BTree.create(store, metadata);

            final BigdataValueFactory vf = BigdataValueFactoryImpl
                    .getInstance(namespace);

            final BlobsIndexHelper h = new BlobsIndexHelper();

            // Write on the TERMS index, obtaining IVs for those BNodes.
            final IV[] ivs1;
            {

                /*
                 * Generate Values that we will use to read and write on the
                 * TERMS index.
                 */
                final BigdataValue[] values;
                {

                    final BigdataBNode bnode1 = vf.createBNode();

                    final BigdataBNode bnode2 = vf.createBNode("abc");

                    values = new BigdataValue[] { bnode1, bnode2 };

                }

                final KVO[] a = h.generateKVOs(vf
                        .getValueSerializer(), values, values.length);

                final byte[][] keys = new byte[a.length][];
                final byte[][] vals = new byte[a.length][];
                for (int i = 0; i < a.length; i++) {
                    keys[i] = a[i].key;
                    vals[i] = a[i].val;
                }

                final boolean readOnly = false;
                final WriteTaskStats stats = new WriteTaskStats();

                final BlobsWriteProc.BlobsWriteProcConstructor ctor = new BlobsWriteProc.BlobsWriteProcConstructor(
                        readOnly, storeBlankNodes);

                ndx.submit(0/* fromIndex */, values.length/* toIndex */, keys,
                        vals, ctor, new BlobsWriteProcResultHandler(a,
                                readOnly, stats));

                // Copy out the assigned IVs.
                ivs1 = new IV[a.length];
                for (int i = 0; i < a.length; i++) {
                    final IV iv = a[i].obj.getIV();
                    assertNotNull(iv);
                    ivs1[i] = iv;
                }

            }

            // Write on the TERMS index, obtaining new IVs for those BNodes.
            final IV[] ivs2;
            {

                /*
                 * Generate Values that we will use to read and write on the
                 * TERMS index (we need distinct instances since the IV once
                 * set can not be cleared from the BigdataValue).
                 */
                final BigdataValue[] values;
                {

                    final BigdataBNode bnode1 = vf.createBNode();

                    final BigdataBNode bnode2 = vf.createBNode("abc");

                    values = new BigdataValue[] { bnode1, bnode2 };

                }

                final KVO[] a = h.generateKVOs(vf
                        .getValueSerializer(), values, values.length);

                final byte[][] keys = new byte[a.length][];
                final byte[][] vals = new byte[a.length][];
                for (int i = 0; i < a.length; i++) {
                    keys[i] = a[i].key;
                    vals[i] = a[i].val;
                }

                final boolean readOnly = false;
                final WriteTaskStats stats = new WriteTaskStats();

                final BlobsWriteProc.BlobsWriteProcConstructor ctor = new BlobsWriteProc.BlobsWriteProcConstructor(
                        readOnly, storeBlankNodes);

                ndx.submit(0/* fromIndex */, values.length/* toIndex */, keys,
                        vals, ctor, new BlobsWriteProcResultHandler(a,
                                readOnly, stats));

                // Copy out the assigned IVs.
                ivs2 = new IV[a.length];
                for (int i = 0; i < a.length; i++) {
                    final IV iv = a[i].obj.getIV();
                    assertNotNull(iv);
                    ivs2[i] = iv;
                }

            }

            /*
             * Verify that all assigned IVs are distinct and that all assigned
             * IVs can be used to materialize the blank nodes that we wrote onto
             * the TERMS index.
             */
            {

                final IKeyBuilder keyBuilder = h.newKeyBuilder(); 
                
                // Same #of IVs.
                assertEquals(ivs1.length, ivs2.length);

                for (int i = 0; i < ivs1.length; i++) {
                    assertNotNull(ivs1[i]);
                    assertNotNull(ivs2[i]);
                    assertNotSame(ivs1[i], ivs2[i]);
                    assertNotNull(h.lookup(ndx, (BlobIV)ivs1[i], keyBuilder));
                    assertNotNull(h.lookup(ndx, (BlobIV)ivs2[i], keyBuilder));
//					assertNotNull(ndx.lookup(ivs1[i]));
//					assertNotNull(ndx.lookup(ivs2[i]));
                }
                
            }

        } finally {

            store.destroy();

        }

    }

	/*
	 * FIXME These tests for hash collisions no longer work because the hash
	 * code is being computed from the original Value which makes the override
	 * of generateKeys() impossible. This makes it quite difficult to unit test
	 * the behavior which handles hash collisions since they are otherwise quite
	 * rare.
	 * 
	 * One way to do this would be to factor out the hash function such that we
	 * could override it explicitly.
	 */
    
//    /**
//     * Unit test with a no collisions.
//     */
//    public void test_noCollisions() {
//
//        doHashCollisionTest(1);
//
//    }
//
//    /**
//     * Unit test with a small number of collisions.
//     */
//    public void test_someCollisions() {
//
//        doHashCollisionTest(12);
//
//    }
//
//    /**
//     * Unit test with a the maximum number of collisions.
//     */
//    public void test_lotsOfCollisions() {
//
//		doHashCollisionTest(255);
//
//	}
//
//	/**
//	 * Unit test with a too many collisions.
//	 */
//	public void test_tooManyCollisions() {
//
//		try {
//			doHashCollisionTest(257);
//			fail("Expecting: " + CollisionBucketSizeException.class);
//		} catch (CollisionBucketSizeException ex) {
//			if (log.isInfoEnabled())
//				log.info("Ignoring expected exception: " + ex);
//		}
//
//	}
//
//	/**
//	 * Test helper attempts to insert the given number of {@link BigdataValue}s
//	 * into the terms index. If the maximum collision bucket size is reached,
//	 * then the exception is thrown back to the caller.
//	 * 

// * Note: This test needs to be done using mock data since it would take a // * huge number of values to have that many collisions otherwise. // * // * @param ncollisions // * The number of collisions to manufacture. // * // * @throws CollisionBucketSizeException // */ // private void doHashCollisionTest(final int ncollisions) { // // final IRawStore store = new SimpleMemoryRawStore(); // // try { // // final TermsIndexHelper h = new TermsIndexHelper(); // // final String namespace = getName(); // // final IndexMetadata metadata = getTermsIndexMetadata(namespace); // // final BTree ndx = BTree.create(store, metadata); // // final BigdataValueFactory vf = BigdataValueFactoryImpl // .getInstance(namespace); // // /* // * Generate Values that we will use to read and write on the TERMS // * index. // */ // final BigdataValue[] values; // { // // final ArrayList tmp = new ArrayList( // ncollisions); // // for (int i = 0; i < ncollisions; i++) { // // final BigdataURI uri = vf // .createURI("http://www.bigdata.com/testTerm/" + i); // // tmp.add(uri); // // } // // values = tmp.toArray(new BigdataValue[ncollisions]); // // } // // final int hashCode = 12; // final KVO[] a = mockGenerateKVOs(vf // .getValueSerializer(), values, values.length, hashCode); // // final byte[][] keys = new byte[a.length][]; // final byte[][] vals = new byte[a.length][]; // for (int i = 0; i < a.length; i++) { // keys[i] = a[i].key; // vals[i] = a[i].val; // // Verify 1st byte decodes to the VTE of the Value. // assertEquals(VTE.valueOf(a[i].obj), AbstractIV // .getVTE(KeyBuilder.decodeByte(a[i].key[0]))); // } // // { // // final boolean readOnly = false; // final boolean storeBlankNodes = false; // final WriteTaskStats stats = new WriteTaskStats(); // // final TermsWriteProc.TermsWriteProcConstructor ctor = new TermsWriteProc.TermsWriteProcConstructor( // readOnly, storeBlankNodes); // // ndx.submit(0/* fromIndex */, values.length/* toIndex */, keys, // vals, ctor, new TermsWriteProcResultHandler(a, // readOnly, stats)); // // // Note: [nunknown] is only set on read. // assertEquals(0, stats.nunknown.get()); // // /* // * Verify that the IV is a fully qualified key for the TERMS // * index. // */ // final IKeyBuilder keyBuilder = h.newKeyBuilder(); // // for (int i = 0; i < a.length; i++) { // // final BigdataValue expectedValue = a[i].obj; // // final IV actualIV = expectedValue.getIV(); // // // Verify an IV was assigned. // assertNotNull(actualIV); // // // Verify the VTE is consistent. // assertEquals(VTE.valueOf(expectedValue), actualIV.getVTE()); // // // Verify that the hashCode is consistent. // assertEquals(expectedValue.hashCode(), actualIV.hashCode()); // // // Encode the IV as a key. // final byte[] key = actualIV.encode(keyBuilder.reset()) // .getKey(); // // // Verify can encode/decode the IV. // { // // final IV decodedIV = IVUtility.decode(key); // // assertEquals(actualIV, decodedIV); // // assertEquals(key, decodedIV.encode(h.newKeyBuilder()) // .getKey()); // // } // // // Point lookup using the IV as the key. // final byte[] val = ndx.lookup(key); // // // Verify point lookup succeeds. // if (val == null) { // fail("Could not resolve IV against index: expectedValue=" // + expectedValue // + ", actualIV=" // + actualIV // + ", key=" + BytesUtil.toString(key)); // } // // // Decode the returned byte[] as a Value. // final BigdataValue actual = vf.getValueSerializer() // .deserialize(val); // // // Verify BigdataValues are equal() // assertEquals(expectedValue, actual); // // if (log.isInfoEnabled()) // log.info("i=" + expectedValue + ", iv=" + actualIV); // // } // // } // // } finally { // // store.destroy(); // // } // // } /** * Create a TERMS index, put some data into it, and verify that we can use * the {@link BlobsTupleSerializer} to access that data, including handling * of the NullIV. */ public void test_TermsTupleSerializer() { final IRawStore store = new SimpleMemoryRawStore(); try { final String namespace = getName(); final BTree ndx = createTermsIndex(store, namespace); final BlobsIndexHelper h = new BlobsIndexHelper(); final BigdataValueFactory vf = BigdataValueFactoryImpl .getInstance(namespace); /* * Generate Values that we will use to read and write on the TERMS * index. */ final BigdataValue[] values; { final BigdataURI uri1 = vf .createURI("http://www.bigdata.com/testTerm"); final BigdataLiteral lit1 = vf.createLiteral("bigdata"); final BigdataLiteral lit2 = vf.createLiteral("bigdata", "en"); final BigdataLiteral lit3 = vf.createLiteral("bigdata", XMLSchema.STRING); final BigdataBNode bnode1 = vf.createBNode(); final BigdataBNode bnode2 = vf.createBNode("abc"); values = new BigdataValue[] { uri1, lit1, lit2, lit3, bnode1, bnode2 }; } final KVO[] a = h.generateKVOs(vf .getValueSerializer(), values, values.length); final byte[][] keys = new byte[a.length][]; final byte[][] vals = new byte[a.length][]; for (int i = 0; i < a.length; i++) { keys[i] = a[i].key; vals[i] = a[i].val; } /* * Write on the TERMS index, setting IVs as side-effect on * BigdataValues. */ { final boolean readOnly = false; final boolean storeBlankNodes = true; final WriteTaskStats stats = new WriteTaskStats(); final BlobsWriteProc.BlobsWriteProcConstructor ctor = new BlobsWriteProc.BlobsWriteProcConstructor( readOnly, storeBlankNodes); ndx.submit(0/* fromIndex */, values.length/* toIndex */, keys, vals, ctor, new BlobsWriteProcResultHandler(a, readOnly, stats)); } /* * Exercise the TermsTupleSerializer */ { final BlobsTupleSerializer tupSer = (BlobsTupleSerializer) ndx .getIndexMetadata().getTupleSerializer(); for(BigdataValue value : values) { final IV iv = value.getIV(); assertNotNull(iv); // Test serializeKey. final byte[] key = tupSer.serializeKey(iv); final byte[] val = ndx.lookup(key); final BigdataValue actualValue = vf.getValueSerializer() .deserialize(val); assertEquals(value, actualValue); /* * TODO It should be possible to test more of the tupleSer * directly. E.g., by running an iterator over the tuples * and visiting them. */ } } } finally { store.destroy(); } } // /** // * Mock variant of // * {@link TermsIndexHelper#generateKVOs(BigdataValueSerializer, BigdataValue[], int)} // * which uses a constant value for the assigned hash codes. // * // * @param valSer // * The object used to generate the values to be written onto the // * index. // * @param terms // * The terms whose sort keys will be generated. // * @param numTerms // * The #of terms in that array. // * @param hashCode // * The hash code to assign to each value. // * // * @return An array of correlated key-value-object tuples. // */ // @SuppressWarnings("unchecked") // static private KVO[] mockGenerateKVOs( // final BigdataValueSerializer valSer, // final BigdataValue[] terms, final int numTerms, final int hashCode) { // // if (valSer == null) // throw new IllegalArgumentException(); // if (terms == null) // throw new IllegalArgumentException(); // if (numTerms <= 0 || numTerms > terms.length) // throw new IllegalArgumentException(); // // final KVO[] a = new KVO[numTerms]; // // final TermsIndexHelper helper = new TermsIndexHelper(); // // final IKeyBuilder keyBuilder = helper.newKeyBuilder(); // // final DataOutputBuffer out = new DataOutputBuffer(); // // final ByteArrayBuffer tmp = new ByteArrayBuffer(); // // for (int i = 0; i < numTerms; i++) { // // final BigdataValue term = terms[i]; // // final VTE vte = VTE.valueOf(term); // // final byte[] key = helper.makePrefixKey(keyBuilder.reset(), vte, // hashCode); // // final byte[] val = valSer.serialize(term, out.reset(), tmp); // // a[i] = new KVO(key, val, term); // // } // // return a; // // } /** * Unit test for {@link BlobsWriteProc.Result} serialization. */ public void test_blobsResultSerialization() { final long totalBucketSize = 7L; final int maxBucketSize = 3; final int[] counters = new int[] { 1, 0, 2, BlobsIndexHelper.NOT_FOUND, 3 }; final BlobsWriteProc.Result given = new BlobsWriteProc.Result( totalBucketSize, maxBucketSize, counters); assertEquals("totalBucketSize", totalBucketSize, given.totalBucketSize); assertEquals("maxBucketSize", maxBucketSize, given.maxBucketSize); assertTrue("counters[]", Arrays.equals(counters, given.counters)); final byte[] b = SerializerUtil.serialize(given); final BlobsWriteProc.Result actual = (BlobsWriteProc.Result) SerializerUtil .deserialize(b); assertEquals("totalBucketSize", totalBucketSize, actual.totalBucketSize); assertEquals("maxBucketSize", maxBucketSize, actual.maxBucketSize); assertTrue("counters[]", Arrays.equals(counters, actual.counters)); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy