/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package projects.blkmgr;

import java.nio.ByteBuffer ;
import java.util.ArrayList ;
import java.util.List ;

import org.openjena.atlas.lib.Pair ;
import org.openjena.atlas.lib.StrUtils ;

import com.hp.hpl.jena.tdb.base.block.BlockException ;

public class ControlBlock
{
    public static void main(String...argv)
    {
        ControlParams params = new ControlParams() ;
        params.freeChain = 10 ;
        params.sequence = 20 ;
        params.roots.add(Pair.create("foo", 100L)) ;
        
        ByteBuffer bb = ByteBuffer.allocate(1000) ;
        
        write(bb, params) ;
        bb.flip() ;
        ControlParams params2 = parse(bb) ;
        if ( !equals(params,params2))
            System.out.println("**** Different") ;
        print(params) ;
        print(params2) ;
    }
    
    
    static final int SizeofInt =    Integer.SIZE/Byte.SIZE ;
    static final int SizeofLong =   Long.SIZE/Byte.SIZE ;
    
    /* Format:
     *   Free chain start (long)
     *   Allocation sequnce number (long)
     *   Roots 
     *      (strlen, bytes, id)
     *      (int, bytes, long)
     *   -1
     */
    
    static class ControlParams
    {
        long freeChain = -1 ;
        long sequence = -1 ;
        List<Pair<String, Long>> roots = new ArrayList<>() ;
    }
    
    static boolean equals(ControlParams cp1, ControlParams cp2)
    {
        if (cp1.freeChain != cp2.freeChain) return false ;
        if (!cp1.roots.equals(cp2.roots)) return false ;
        if (cp1.sequence != cp2.sequence) return false ;
        return true ;
    }
    
    static ControlParams parse(ByteBuffer bb)
    {
        ControlParams params = new ControlParams() ;
        int idx = 0 ;
        bb.position(0) ;
        
        params.freeChain = bb.getLong() ;
        idx += SizeofLong ;
        
        params.sequence = bb.getLong() ;
        idx += SizeofLong ;
        
        while (bb.position() < bb.limit() )
        {
            if ( idx != bb.position() )
                throw new BlockException("Misaligned") ;

            int len = bb.getInt() ;
            idx += SizeofInt ;
            if ( len < 0 )
                break ;
            
            byte[] b = new byte[len] ;
            bb.get(b) ;
            idx += len ;
            String key = StrUtils.fromUTF8bytes(b) ;
            
            Long rootId =  bb.getLong() ;
            idx += SizeofLong ;
            
            params.roots.add(Pair.create(key, rootId)) ;
        }
        
        return params ;
    }
    
    static void print(ControlParams params)
    {
        System.out.println("free chain: " + params.freeChain) ;
        System.out.println("sequence:   " + params.sequence) ;
        for ( Pair<String, Long> r : params.roots )
            System.out.printf("  %d : %s\n", r.getRight(), r.getLeft()) ;
        System.out.println("roots = "+params.roots.size()) ;
    }
    
    static void write(ByteBuffer bb, ControlParams params)
    {
        bb.position(0) ;
        bb.putLong(params.freeChain) ;
        bb.putLong(params.sequence) ;
        for ( Pair<String, Long> r : params.roots )
        {
            byte[] b = StrUtils.asUTF8bytes(r.getLeft()) ;
            bb.putInt(b.length) ;
            bb.put(b) ;
            bb.putLong(r.getRight()) ;
        }
        bb.putInt(-1) ;
    }
}


@@ -992,61 +992,45 @@
 s ;%0A
-%0A
 import 
-com.hp.hpl.jena.tdb.base.block.BlockException
+org.openjena.atlas.logging.Log
  ;%0A%0A
@@ -1266,17 +1266,122 @@
 (%22foo%22, 
-1
+-1L)) ;%0A        params.roots.add(Pair.create(%22%22,    200L)) ;%0A        params.roots.add(Pair.create(%22bar%22, 3
 00L)) ;%0A
@@ -2567,30 +2567,8 @@
 ) ;%0A
-        int idx = 0 ;%0A
     
@@ -2643,45 +2643,8 @@
 ) ;%0A
-        idx += SizeofLong ;%0A        %0A
     
@@ -2692,319 +2692,110 @@
     
-idx += SizeofLong ;%0A        %0A        while (bb.position() %3C bb.limit() )%0A        %7B%0A            if ( idx != bb.position() )%0A                throw new BlockException(%22Misaligned%22) ;%0A%0A            int len = bb.getInt() ;%0A            idx += SizeofInt ;%0A            if ( len %3C 0 )%0A                break ;%0A            
+%0A        while (true)%0A        %7B%0A            int len = bb.getInt() ;%0A            if ( len %3C 0 ) break ;
 %0A   
@@ -2858,33 +2858,8 @@
 ) ;%0A
-            idx += len ;%0A
     
@@ -2907,29 +2907,16 @@
 es(b) ;%0A
-            %0A
         
@@ -2932,17 +2932,16 @@
 rootId =
- 
  bb.getL
@@ -2965,39 +2965,118 @@
    i
-dx += SizeofLong ;%0A            
+f ( params.roots.contains(key) )%0A                Log.warn(ControlBlock.class, %22Duplicate key for roots map%22) ;
 %0A   
@@ -3139,25 +3139,16 @@
       %7D%0A
-        %0A
         

Remove idx tracking