001    /**
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.fusesource.hawtdb.api;
018    
019    import org.fusesource.hawtdb.internal.page.Extent;
020    import org.fusesource.hawtdb.internal.page.ExtentInputStream;
021    import org.fusesource.hawtdb.internal.page.ExtentOutputStream;
022    import org.fusesource.hawtdb.internal.util.Ranges;
023    
024    import java.io.DataInputStream;
025    import java.io.DataOutputStream;
026    import java.io.IOException;
027    import java.util.Collections;
028    import java.util.List;
029    
030    /**
031     * Abstract base class for implementations of EncoderDecoder which use stream encoding/decoding.
032     * 
033     * @author <a href="http://hiramchirino.com">Hiram Chirino</a>
034     */
035    abstract public class AbstractStreamPagedAccessor<T>  implements PagedAccessor<T> {
036    
037        public List<Integer> store(Paged paged, int page, T data) {
038            // The node will be stored in an extent. This allows us to easily
039            // support huge nodes.
040            // The first extent is only 1 page long, extents linked off
041            // the first page will be up to 128 pages long.
042            ExtentOutputStream eos = new ExtentOutputStream(paged, page, (short) 1, (short) 128);
043            DataOutputStream os = new DataOutputStream(eos);
044            try {
045                encode(paged, os, data);
046                os.close();
047            } catch (IOException e) {
048                throw new IndexException(e);
049            }
050    
051            Ranges pages = eos.getPages();
052            pages.remove(page);
053            if (pages.isEmpty()) {
054                return Collections.emptyList();
055            }
056    
057            return pages.values();
058        }
059    
060        public T load(Paged paged, int page) {
061            ExtentInputStream eis = new ExtentInputStream(paged, page);
062            DataInputStream is = new DataInputStream(eis);
063            try {
064                return decode(paged, is);
065            } catch (IOException e) {
066                throw new IndexException(e);
067            } finally {
068                try {
069                    is.close();
070                } catch (Throwable ignore) {
071                }
072            }
073    
074        }
075    
076        public List<Integer> pagesLinked(Paged paged, int page) {
077            return Extent.pagesLinked(paged, page);
078        }
079    
080    
081        abstract protected void encode(Paged paged, DataOutputStream os, T data) throws IOException;
082        abstract protected T decode(Paged paged, DataInputStream is) throws IOException;
083    }