/*
 * This file is part of the Poliqarp suite.
 * 
 * Copyright (C) 2004-2009 by Instytut Podstaw Informatyki Polskiej
 * Akademii Nauk (IPI PAN; Institute of Computer Science, Polish
 * Academy of Sciences; cf. www.ipipan.waw.pl).  All rights reserved.
 * 
 * This file may be distributed and/or modified under the terms of the
 * GNU General Public License version 2 as published by the Free Software
 * Foundation and appearing in the file gpl.txt included in the packaging
 * of this file.  (See http://www.gnu.org/licenses/translations.html for
 * unofficial translations.)
 * 
 * A commercial license is available from IPI PAN (contact
 * Michal.Ciesiolka@ipipan.waw.pl or ipi@ipipan.waw.pl for more
 * information).  Licensees holding a valid commercial license from IPI
 * PAN may use this file in accordance with that license.
 * 
 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING
 * THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE.
 */

/**
 * @file merge-output.h
 * @brief Multiway merge output.
 *
 * Second stage of indexing is done by merging all the sorted runs into
 * one. To this end, the indexer maintains a heap of runs, continuously
 * retrieving from it the occurrence that fits next into the order and
 * recompressing it (note that the information about term frequencies is
 * now known). 
 *
 * This file defines a structure that aids in storing and recompressing
 * the sorted occurrences. It can be used as a backend for an output
 * bitstream.
 */

#ifndef POLIQARP_MERGE_OUTPUT_H
#define POLIQARP_MERGE_OUTPUT_H

#include <sakura/common/bitstream.h>
#include <sakura/common/bs-file-backend.h>

#include "block-list.h"
#include "occurrences.h"
#include "vector.h"

/**
 * A backend for an output bitstream that emits physically non-contiguous
 * sequence of blocks to a file, remembering the order of blocks so that
 * they can be later rearranged to be contiguous.
 */
struct merge_output {
   struct file_obs fobs;               /**< An internal backend structure. */
   uint32_t blocks_written;            /**< Number of blocks written by this
                                            backend to the file. */
   size_t current_block;               /**< Physical index of the block 
                                            currently being filled. */
   struct free_block_list *block_list; /**< List of free blocks. */
   struct vector *frequencies;         /**< Frequencies of terms. */
   struct obs obs;                     /**< The bitstream that this structure
                                            serves as a backend for. */
   uint32_t b;                         /**< Parameter of output Golomb code. */
   uint32_t num_documents;             /**< Number of documents in the file --
                                            used to calculate b. */
   struct occurrence current;          /**< Lastly processed occurrence. */
   FILE *offsets;                      /**< File containing list of offsets of
                                            compressed occurrences lists. */
};

/**
 * Creates a merge output backend.
 * @param output the backend to be created.
 * @param occ occurrences data used to initialize the backend.
 * @param block_list list of free blocks.
 * @param offsets file of offsets.
 */
void merge_output_create(struct merge_output *output, struct occurrences *occ,
   struct free_block_list *block_list, FILE *offsets);

/**
 * Destroys a merge output backend.
 * @param output the backend to be destroyed.
 */
void merge_output_destroy(struct merge_output *output);

/**
 * Flushes data from the internal buffer of the backend to disk.
 * @param output the backend to be flushed.
 */
int merge_output_flush(struct merge_output *output);

/**
 * Adds an occurrence to the output file, compressing it using Golomb code.
 * @param output the backend to output the occurrence to.
 * @param what the occurrence to be written.
 */
void merge_output_occurrence(struct merge_output *output,
   struct occurrence *what);

/**
 * Returns the number of bytes written heretofore by this backend.
 * @param output the backend.
 * @return number of bytes consumed.
 */
off64_t merge_output_get_bytes_count(struct merge_output *output);

#endif /* POLIQARP_MERGE_OUTPUT_H */
