/* DefaultPointerIndex.java * * Copyright (c) 2003, Benja Fallenstein * * This file is part of Storm. * * Storm is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Storm 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 Lesser General * Public License for more details. * * You should have received a copy of the GNU Lesser General * Public License along with Storm; if not, write to the Free * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA * * */ /* * Written by Benja Fallenstein */ package org.nongnu.storm.impl; import org.nongnu.storm.*; import org.nongnu.storm.util.HexUtil; import java.io.*; import java.util.*; public class DefaultPointerIndex implements PointerIndexType.Index { protected IndexedPool pool; protected IndexedPool.DB db; protected DefaultPointerIndex(IndexedPool pool, IndexedPool.DB db) { this.pool = pool; this.db = db; } public Pointer getPointer(String uri) throws IOException { return new DefaultPointer(uri); } protected class DefaultPointer implements Pointer { protected String uri; protected byte[] uriBytes; protected DefaultPointer(String uri) throws IOException { this.uri = uri; this.uriBytes = uri.getBytes("US-ASCII"); } public String getURI() { return uri; } public IndexedPool getPool() { return pool; } public Set getAllBlocks() throws IOException { Collector mappings = db.get(uriBytes); Set blocks = new HashSet(); for(Iterator i=mappings.iterator(); i.hasNext();) { IndexedPool.Mapping m = (IndexedPool.Mapping)i.next(); byte[] b = m.value; byte[] targetBytes = new byte[b[0]]; System.arraycopy(b, 1, targetBytes, 0, b[0]); BlockId target = new BlockId(targetBytes); Set obsolete = new HashSet(); int pos = b[0]+1; while(pos < b.length) { int w = b[pos]; byte[] id = new byte[w]; System.arraycopy(b, pos+1, id, 0, w); obsolete.add(new BlockId(id)); pos += w + 1; } blocks.add(new DefaultPointerBlock(m.block, target, obsolete)); } return blocks; } public Set getCurrentBlocks() throws IOException { Set blocks = getAllBlocks(); Set obsoleted = new HashSet(); for(Iterator i=blocks.iterator(); i.hasNext();) { DefaultPointerBlock b = (DefaultPointerBlock)i.next(); obsoleted.addAll(b.getObsoleted()); } for(Iterator i=blocks.iterator(); i.hasNext();) { DefaultPointerBlock b = (DefaultPointerBlock)i.next(); if(obsoleted.contains(b.getBlock().getId())) i.remove(); } return blocks; } protected class DefaultPointerBlock implements PointerBlock { protected Block block; protected BlockId target; protected Set obsoleted; protected DefaultPointerBlock(BlockId block, BlockId target, Set obsoleted) throws IOException { this.block = pool.get(block); this.target = target; this.obsoleted = obsoleted; } public Pointer getPointer() { return DefaultPointer.this; } public BlockId getTarget() { return target; } public Block getBlock() { return block; } public Set getObsoleted() { return obsoleted; } public PointerBlock update(BlockId newTarget) throws IOException { return addPointerBlock(newTarget, Collections.singleton(block.getId())); } public boolean equals(Object o) { if(!(o instanceof DefaultPointerBlock)) return false; DefaultPointerBlock b = (DefaultPointerBlock)o; return b.getPointer().getPool() == pool && b.block.getId().equals(block.getId()); } public int hashCode() { return (pool.hashCode()+50) ^ block.getId().hashCode(); } } public PointerBlock addPointerBlock(BlockId target, Set obsoleteBlocks) throws IOException { BlockOutputStream bos = pool.getBlockOutputStream(PointerIndexType.contentType); bos.write("GZZPTR0\n".getBytes("US-ASCII")); bos.write(uriBytes); bos.write((byte)'\n'); if(!target.getURI().startsWith("storm:block:")) throw new Error(); String hex = target.getURI().substring("storm:block:".length()); bos.write(hex.getBytes("US-ASCII")); bos.write((byte)'\n'); for(Iterator i=obsoleteBlocks.iterator(); i.hasNext();) { BlockId id = (BlockId)i.next(); if(!id.getURI().startsWith("storm:block:")) throw new Error(); hex = id.getURI().substring("storm:block:".length()); bos.write(hex.getBytes("US-ASCII")); bos.write((byte)'\n'); } bos.close(); return new DefaultPointerBlock(bos.getBlockId(), target, obsoleteBlocks); } } }