<commit_before>/*
// $Id$
// Fennel is a relational database kernel.
// Copyright (C) 2004-2004 John V. Sichi.
//
// This program 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.1
// of the License, or (at your option) any later version.
//
// 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser 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.
*/

FENNEL_BEGIN_CPPFILE("$Id$");

/**

Overview

The Fennel XO scheduler is responsible for determining which execution streams
to run and in what order (or with what parallelization).  In addition, the
scheduler is responsible for the actual invocation of XO execution methods.  A
more modular design would separate scheduling from execution, but there is
currently no justification for the extra complexity this separation would
introduce.

Interfaces

The UML static structure diagram below illustrates the relevant relationships
(only attributes and methods relevant to scheduling are shown):

\image html SchedulerInterfaces.gif

An ExecutionStreamScheduler may be dedicated per ExecutionStreamGraph, or may
be responsible for multiple graphs, depending on the scheduling granularity
desired.  Each graph consists of multiple vertex instances of ExecutionStream,
with ExecutionStreamBuffer edges representing dataflow.  Each buffer is
assigned a single producer/consumer stream pair.  Hence, the number of buffers
accessible from a stream is equal to its vertex degree in the graph.
The design goal is that the ExecutionStreamBuffer representation should
remain very simple, with any complex buffering strategies
(e.g. disk-based queueing) encapsulated as specialized stream
implementations instead.

When the scheduler decides that a particular stream should run, it invokes its
ExecutionStream::execute method, passing a reference to an instance of
ExecutionStreamQuantum to limit the amount of data processed.  The exact
interpretation of the quantum is up to the stream implementation.  The stream's
response is dependent on the states of its incident buffers, which usually
change as a side-effect of the execution.  This protocol is specified in more
detail later on.

It is up to a scheduler implementation to keep track of the runnable
status of each stream.  This information is based on the result of
each call to ExecutionStream::execute (including the return code and incident
buffer state changes), and can be queried via
ExecutionStreamScheduler::isRunnable.  In addition,
ExecutionStreamScheduler::makeRunnable can be invoked explicitly to alert the
scheduler to an externally-driven status change (e.g. arrival of a network
packet or completion of asynchronous disk I/O requested by a stream).  A stream
may call ExecutionStreamScheduler::setTimer to automatically become runnable
periodically.

Where possible, execution streams should be implemented as non-blocking to
ensure scheduling flexibility.  Streams that may block must return true from
the ExecutionStream::mayBlock method; schedulers may choose to use threading to
prevent such streams from blocking the execution of the scheduler itself.

Scheduler Extensibility

Most of the interfaces involved in scheduling are polymorphic:

Derived classes of ExecutionStreamScheduler implement different scheduling
policies (e.g. sequential vs. parallel, or full-result vs. top-N).

Derived classes of ExecutionStream implement different kinds of data
processing (e.g. table scan, sorting, join, etc).

Derived classes of ExecutionStreamBuffer may contain additional attributes
representing scheduler-specific buffer state (e.g. a timestamp for implementing
some fairness policy).  Because ExecutionStreamScheduler acts as a factory for
buffer instances, it can guarantee that all of the buffers it manages are of
the correct type, and can also create any necessary indexing structures over
those buffers for efficiency of the scheduling algorithm.

Derived classes of ExecutionStreamQuantum may provide scheduler-specific
quantization limits to streams that can understand it.  This requires the code
that constructs an ExecutionStreamGraph to be aware of the kind of scheduler
that will be used to execute it.  Streams which only understand the generic
quantization can be used in any graph.

Top-level Flow

The flow for instantiation and scheduling of a single stream graph is as
follows:

The caller instantiates an ExecutionStreamGraph together with the
ExecutionStream instances it contains.  (See ExecutionStreamBuilder and
ExecutionStreamFactory.)

The caller instantiates an ExecutionStreamScheduler and associates the
graph with it (TODO methods for this).  Internally, the
ExecutionStreamScheduler allocates one instance of ExecutionStreamBuffer for
each dataflow edge in the graph (as well as one for each input or output to the
graph) and notifies the incident streams of its existence.  Once a graph and
its streams have been associated with a scheduler in this way, they may never
be moved to another scheduler.  Buffers start out in state EXECBUF_IDLE, with
pStart, pEnd, and nTuples all zero.  Buffer provision settings are recorded
for use in sanity checking later.

The caller invokes ExecutionStreamGraph::open().

The caller invokes ExecutionStreamScheduler::start().

The caller invokes ExecutionStreamScheduler::readStreamBuffer to read query
output data, and/or ExecutionStreamScheduler::writeStreamBuffer to write query
input data.  This is repeated indefinitely.  Optionally, the caller may invoke
ExecutionStreamScheduler::abort from another thread while a read or write is in
progress; the abort call returns immediately, but the abort request may take
some time to be fulfilled.

The caller invokes ExecutionStreamScheduler::stop().  This is synchronous
and does not return until all execution in other scheduler threads has
completed.

The caller invokes ExecutionStreamGraph::close().

ExecutionStream::execute Protocol

When the scheduler invokes a stream, the possible responses are enumerated by
ExecutionStreamResult:

EXECRC_NEED_INPUT: the invoked stream could not perform any work because it
needed data from at least one of its inputs.  Before return, the invoked stream
is responsible for changing the state of the corresponding input buffers to
EXECBUF_NEED_PRODUCTION.  If the buffer's dataflow mode is CONSUMER_PROVISION,
then the invoked stream is also responsible for setting the buffer pStart and
pEnd pointers to the memory area which the producer should fill with tuples;
otherwise these pointers should be zeroed.

EXECRC_NEED_OUTPUTBUF: the invoked stream could not perform any work
because it needed space in at least one of its output buffers which has not yet
been consumed by the corresponding downstream XO (the output buffer was
still in state EXECBUF_NEED_CONSUMPTION).

EXECRC_EOS: end of stream has been detected; no more data
will ever be produced by the invoked stream.  Before return, the invoked stream
is responsible for setting the state of all of its output buffers to
EXECBUF_EOS, and resetting their pStart/pEnd/nTuples fields to zero.

EXECRC_SUCCESS: the stream produced at least one tuple in one of its
output buffers.  The invoked stream is responsible for a number of state
changes in this case:

Any partially consumed input buffer should have its nTuples field
    decremented and pStart advanced accordingly.

Any fully consumed input buffer should have its nTuples field reset to
    0.  The buffer's state field should change to either EXECBUF_IDLE (in which
    case pStart/pEnd should be zeroed) or EXECBUF_NEED_PRODUCTION (with the
    same rules for pStart/pEnd as for EXECRC_NEED_INPUT).

An output buffer in which tuples were produced should change state to
    EXECBUF_NEED_CONSUMPTION with a nonzero value in its nTuples field.  If the
    buffer's dataflow mode is PRODUCER_PROVISION, then pStart/pEnd should
    reference the area of the producer's memory filled with tuples; otherwise,
    the pEnd pointer set by the consumer should be decremented to the end of
    the last tuple written into the consumer's memory by the invoked stream.

From the point of view of a buffer, this means the possible transitions are as
follows:

\image html SchedulerBufferStatechart.gif

Note that multi-threaded schedulers must guarantee that both streams adjacent
to a buffer are never running simultaneously; this eliminates the need to
synchronize fine-grained access to buffer state.

Example Graph

To help explain the abstractions described so far, the UML object diagram
below shows a simple query stream graph with associated scheduler and buffers:

\image html SchedulerObjectDiagram.gif

This graph corresponds to a simple query like
SELECT name FROM emps WHERE age > 30.  Note that although
four buffer instances are created, the two instances of
ConsumerToProducerProvisionAdapter are the only streams that actually
allocate any memory.  The BTreeScan writes into the memory allocated by
adapter1 above it, which is also read by the calculator; the calculator
writes into the memory allocated by adapter2 above it, which is also read by
the caller via readStreamBuffer.

DfsTreeExecutionStreamScheduler

A reference implementation of the ExecutionStreamScheduler interface is
provided by the DfsTreeExecutionStreamScheduler class, which is suitable as a
no-frills implementation of a traditional lazy non-parallel query execution.

The algorithm used by this scheduler is as follows:

The start method asserts that each of the graphs associated with the
scheduler is a forest of trees (each stream has at most one consumer, and no
cycles exist).

The readStreamBuffer method is the real entry point for synchronous
traversal of the tree.  (writeStreamBuffer is not supported.)

The scheduler asserts that the stream with which readStreamBuffer was
invoked has no consumers (i.e. it is the root of a tree) and has output buffer
provision mode PRODUCER_PROVISION.  The scheduler also asserts that the root
output buffer's mode is not EXECBUF_NEED_CONSUMPTION.  A current
stream pointer is set to reference this stream, and the stream's state is
set to EXECBUF_NEED_PRODUCTION.

VISIT_VERTEX:

If the scheduler's abort flag has been set asynchronously, the
traversal terminates.

The scheduler iterates over each of the input buffers of the current stream
in order.  If it encounters one having state EXECRC_NEED_INPUT, the scheduler
updates its current stream pointer to the corresponding producer stream, and
loops back to label VISIT_VERTEX.

The scheduler invokes the current stream's execute method, and asserts that
the return code was not EXECRC_NEED_OUTPUTBUF (impossible due to
lazy evaluation order).

If the return code was EXECRC_SUCCESS or EXECRC_EOS, then the scheduler
updates the current stream pointer to reference the current stream's parent and
then loops back to label VISIT_VERTEX.  If the current stream has no parent,
the traversal terminates instead.

The scheduler asserts that the return code was EXECRC_NEED_INPUT.  It then
iterates over each of the input buffers of the current stream, asserting that
at least one of them has state EXECBUF_NEED_PRODUCTION (otherwise the scheduler
is stuck in an infinite loop).  The scheduler then loops back to label
VISIT_VERTEX.

DfsTreeExecutionStreamScheduler does not support asynchronous runnability
changes (makeRunnable and setTimer).

TBD:  additional assertions; re-entrancy issues for Java XO's.

Example Execution

Putting together the example graph shown earlier with the
DfsTreeExecutionStreamScheduler algorithm, an example execution trace
might read as follows for a table of five rows:

caller invokes readStreamBuffer on scheduler with adapter2 as argument.

scheduler calls execute on adapter2.  adapter2 sets buf3's state to
EXECBUF_NEED_PRODUCTION and points its pStart/pEnd to its allocated cache page.
adapter2 returns EXECRC_NEED_INPUT.

scheduler calls execute on calc.  calc sets buf2's state to
EXECBUF_NEED_PRODUCTION.  calc returns EXECRC_NEED_INPUT.

scheduler calls execute on adapter1.  adapter1 sets buf1's state to
EXECBUF_NEED_PRODUCTION and points its pStart/pEnd to its
allocated cache page.  adapter1 returns EXECRC_NEED_INPUT.

scheduler calls execute on scan.  scan writes five tuples into buf1, sets
its state to EXECBUF_NEED_CONSUMPTION, adjusts its pEnd to point after fifth
tuple, sets its nTuples to 5, and returns EXECRC_SUCCESS.

scheduler calls execute on adapter1.  adapter1 copies pStart/pEnd/nTuples
from buf1 to buf2, then zeroes buf1 and sets its state to EXECBUF_IDLE.
adapter1 sets buf2's state to EXECBUF_NEED_CONSUMPTION and returns
EXECRC_SUCCESS.

scheduler calls execute on calc.  calc applies filter and consumes all
rows from buf2, zeroing it and setting its state to EXECBUF_IDLE.
calc writes three rows into buf3, adjusting its pEnd to point after
third tuple, and sets its state to EXECBUF_NEED_CONSUMPTION.
calc returns EXECRC_SUCCESS.

scheduler calls execute on adapter2.  adapter2 copies pStart/pEnd/nTuples
from buf3 to buf4, then zeroes buf3 and sets its state to EXECBUF_IDLE.
adapter2 sets buf4's state to EXECBUF_NEED_CONSUMPTION.  adapter2 returns
EXECRC_SUCCESS.

scheduler returns to caller with EXECRC_SUCCESS, giving it
a reference to buf4.

caller reads the data from buf4 and zeroes it, setting its state to
EXECBUF_IDLE.

caller invokes readStreamBuffer on adapter2 again.

scheduler calls execute on adapter2, which returns EXECRC_NEED_INPUT;
same thing repeats all the way down the tree.

scheduler calls execute on scan, which zeroes buf1, sets its state to
EXECBUF_EOS, and eturns EXECRC_EOS.

scheduler calls execute on adapter1, which returns EXECRC_EOS, etc.

scheduler calls execute on calc, which returns EXECRC_EOS, etc.

scheduler calls execute on adapter2, which returns EXECRC_EOS, etc.

scheduler returns to caller with EXECRC_EOS.

TODO:  an animated visualization would be more useful.

Note that most real executions will be much more complicated due to
joins and partial consumption of input.

 */
struct SchedulerDesign
{
    // NOTE:  dummy class for doxygen
};

FENNEL_END_CPPFILE("$Id$");

// End SchedulerDesign.cpp
<commit_msg>FENNEL:  update scheduler design doc<commit_after>/*
// $Id$
// Fennel is a relational database kernel.
// Copyright (C) 2004-2004 John V. Sichi.
//
// This program 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.1
// of the License, or (at your option) any later version.
//
// 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser 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.
*/

FENNEL_BEGIN_CPPFILE("$Id$");

/**

Overview

The Fennel XO scheduler is responsible for determining which execution streams
to run and in what order (or with what parallelization).  In addition, the
scheduler is responsible for the actual invocation of XO execution methods.  A
more modular design would separate scheduling from execution, but there is
currently no justification for the extra complexity this separation would
introduce.

Interfaces

The UML static structure diagram below illustrates the relevant relationships
(only attributes and methods relevant to scheduling are shown):

\image html SchedulerInterfaces.gif

An ExecStreamScheduler may be dedicated per ExecStreamGraph, or may
be responsible for multiple graphs, depending on the scheduling granularity
desired.  Each graph consists of multiple vertex instances of ExecStream,
with ExecStreamBufAccessor edges representing dataflow.  Each buffer accessor is
assigned a single producer/consumer stream pair.  Hence, the number of buffers
accessible from a stream is equal to its vertex degree in the graph.
The design goal is that the ExecStreamBufAccessor representation should
remain very simple, with any complex buffering strategies
(e.g. disk-based queueing) encapsulated as specialized stream
implementations instead.

When the scheduler decides that a particular stream should run, it invokes its
ExecStream::execute method, passing a reference to an instance of
ExecStreamQuantum to limit the amount of data processed.  The exact
interpretation of the quantum is up to the stream implementation.  The stream's
response is dependent on the states of its adjacent buffers, which usually
change as a side-effect of the execution.  This protocol is specified in more
detail later on.

It is up to a scheduler implementation to keep track of the runnable
status of each stream.  This information is based on the result of
each call to ExecStream::execute (including the return code and incident
buffer state changes), and can be queried via
ExecStreamScheduler::isRunnable.  In addition,
ExecStreamScheduler::makeRunnable can be invoked explicitly to alert the
scheduler to an externally-driven status change (e.g. arrival of a network
packet or completion of asynchronous disk I/O requested by a stream).  A stream
may call ExecStreamScheduler::setTimer to automatically become runnable
periodically.

Where possible, execution streams should be implemented as non-blocking to
ensure scheduling flexibility.  Streams that may block must return true from
the ExecStream::mayBlock method; schedulers may choose to use threading to
prevent invocation of such streams from blocking the execution of the scheduler
itself.

Scheduler Extensibility

Most of the interfaces involved in scheduling are polymorphic:

Derived classes of ExecStreamScheduler implement different scheduling
policies (e.g. sequential vs. parallel, or full-result vs. top-N).

Derived classes of ExecStream implement different kinds of data
processing (e.g. table scan, sorting, join, etc).

Derived classes of ExecStreamBufAccessor may contain additional attributes
representing scheduler-specific buffer state (e.g. a timestamp for implementing
some fairness policy).  Because ExecStreamScheduler acts as a factory for
accessor instances, it can guarantee that all of the accessors it manages are of
the correct type, and can also create any necessary indexing structures over
those accessors for efficiency of the scheduling algorithm.

Derived classes of ExecStreamQuantum may provide scheduler-specific
quantization limits to streams that can understand it.  This requires the code
that constructs an ExecStreamGraph to be aware of the kind of scheduler
that will be used to execute it.  Streams which only understand the generic
quantization can be used in any graph.

Top-level Flow

The flow for instantiation and scheduling of a single stream graph is as
follows:

The caller instantiates an ExecStreamGraph together with the
ExecStream instances it contains.  (See ExecStreamBuilder and
ExecStreamFactory.)

The caller instantiates an ExecStreamScheduler and associates the graph
with it (TODO methods for this).  Internally, the ExecStreamScheduler allocates
one instance of ExecStreamBufAccessor for each dataflow edge in the graph (as
well as one for each input or output to the graph) and notifies the adjacent
streams of its existence.  Once a graph and its streams have been associated
with a scheduler in this way, they may never be moved to another scheduler.
Buffer accessors start out in state EXECBUF_IDLE.  Buffer provision settings
are recorded for use in sanity checking later.

The caller invokes ExecStreamGraph::open().

The caller invokes ExecStreamScheduler::start().

The caller invokes ExecStreamScheduler::readStreamBuffer() to read query
output data, and/or ExecStreamScheduler::writeStreamBuffer() to write query
input data.  This is repeated indefinitely.  Optionally, the caller may invoke
ExecStreamScheduler::abort() from another thread while a read or write is in
progress; the abort call returns immediately, but the abort request may take
some time to be fulfilled.

The caller invokes ExecStreamScheduler::stop().  This is synchronous
and does not return until all execution in other scheduler threads has
completed.

The caller invokes ExecStreamGraph::close().

ExecStream::execute Protocol

When the scheduler invokes a stream, the stream attempts to perform its work,
possibly consuming input and/or producing output:

The stream tests for the presence of input data by calling getState() on
its input buffer accessors.

The stream accesses the input data via getConsumptionStart() and
getConsumptionEnd(), and consumes it by calling consumeData().  Consumption may
cause the buffer state to change from EXECBUF_NEED_CONSUMPTION to EXECBUF_IDLE.

When the stream knows that it needs more input data to make progress but
the input buffer is empty, it calls requestProduction() to change the state to
EXECBUF_NEED_PRODUCTION.  If the stream is responsible for providing the input
buffer memory, it must also call provideBufferForProduction() in this case to
set up the memory area which the upstream producer should fill.

If the stream is responsible for providing an output buffer, it produces
data by calling provideBufferForConsumption().  Otherwise, it produces data by
calling getProductionStart() and getProductionEnd() to access the output memory
area provided by the downstream consumer, and then calls produceData() to
indicate how much of that area it filled.  In either case, the resulting state
of the output buffer is EXECBUF_NEED_CONSUMPTION.

When the stream knows that no more data will ever be produced on a
particular output, it should call markEOS() on the corresponding buffer
accessor.

The possible responses from the execute call are enumerated by
ExecStreamResult:

EXECRC_NEED_INPUT: the invoked stream could not produce any output because
it exhausted the data from at least one of its inputs.

EXECRC_NEED_OUTPUTBUF: the invoked stream could not produce any output
because it needed space in at least one of its output buffers which has not yet
been consumed by the corresponding downstream XO.

EXECRC_EOS: the invoked stream did not produce any output because its end
has been reached; no more data will ever be produced by this stream.  In this
case, the invoked stream is responsible for calling markEOS() on all of
its output buffers.

EXECRC_NO_OUTPUT: the invoked stream did not produce any output for some
reason other than NEED_INPUT/NEED_OUTPUTBUF/EOS.  An example would be a stream
which periodically becomes runnable to poll a data source; when no new
data is available, EXECRC_NO_OUTPUT is the appropriate result.

EXECRC_OUTPUT: the stream produced data in at least one of its
output buffers.

From the point of view of a buffer, this means the possible transitions are as
follows:

\image html SchedulerBufferStatechart.gif

Note that multi-threaded schedulers must guarantee that both streams adjacent
to a buffer are never running simultaneously; this eliminates the need to
synchronize fine-grained access to buffer state.

Example Graph

To help explain the abstractions described so far, the UML object diagram
below shows a simple query stream graph with associated scheduler and buffers:

\image html SchedulerObjectDiagram.gif

This graph corresponds to a simple query like
SELECT name FROM emps WHERE age > 30.  Note that although
four buffer instances are created, the two instances of
ConsumerToProducerProvisionAdapter are the only streams that actually
allocate any memory.  The BTreeScan writes into the memory allocated by
adapter1 above it, which is also read by the calculator; the calculator
writes into the memory allocated by adapter2 above it, which is also read by
the caller via readStreamBuffer.

Producer Provision of Buffer Memory

When a buffer accessor's provision mode is set to PRODUCER_PROVISION,
the producer is responsible for providing buffer memory.  The diagram
below illustrates the call sequence between producer and
consumer:

\image html SchedulerProducerProvision.gif

First, the calc stream (the consumer) requests production but does
not provide any buffer.  Next, the adapter stream (the producer)
provides a buffer full of data.  Finally, the consumer accesses the
data via getConsumptionStart/End, marking how much it read via the
consumeData call.

Consumer Provision of Buffer Memory

For CONSUMER_PROVISION, the call sequence is different:

\image html SchedulerConsumerProvision.gif

First, the adapter stream (the consumer) requests production AND provides
an empty buffer.  Next,
the calc stream (the producer) determines the buffer bounds with
getProductionStart/End and
then writes tuples into the buffer, marking the end of data with the
produceData call.  Finally, the consumer accesses the data in the buffer via
getConsumptionStart/End.

DfsTreeExecStreamScheduler

A reference implementation of the ExecStreamScheduler interface is
provided by the DfsTreeExecStreamScheduler class, which is suitable as a
no-frills implementation of a traditional lazy non-parallel query execution.

The algorithm used by this scheduler is as follows:

The start method asserts that each of the graphs associated with the
scheduler is a forest of trees (each stream has at most one consumer, and no
cycles exist).

The readStreamBuffer() method is the real entry point for synchronous
traversal of the tree.  (writeStreamBuffer() is not supported.)

The scheduler asserts that the stream with which readStreamBuffer() was
invoked has no consumers (i.e. it is the root of a tree) and has output buffer
provision mode PRODUCER_PROVISION.  The scheduler also asserts that the root
output buffer's mode is not EXECBUF_NEED_CONSUMPTION.  A current
stream pointer is set to reference this stream, and the stream's state is
set to EXECBUF_NEED_PRODUCTION.

VISIT_VERTEX:

If the scheduler's abort flag has been set asynchronously, the
traversal terminates.

The scheduler iterates over each of the input buffers of the current stream
in order.  If it encounters one having state EXECRC_NEED_INPUT, the scheduler
updates its current stream pointer to the corresponding producer stream, and
loops back to label VISIT_VERTEX.

The scheduler invokes the current stream's execute method, and asserts that
the return code was neither EXECRC_NEED_OUTPUTBUF nor EXECRC_NO_OUTPUT
(impossible due to lazy evaluation order).

If the return code was EXECRC_OUTPUT or EXECRC_EOS, then the scheduler
updates the current stream pointer to reference the current stream's parent and
then loops back to label VISIT_VERTEX.  If the current stream has no parent,
the traversal terminates instead.

The scheduler asserts that the return code was EXECRC_NEED_INPUT.  It then
iterates over each of the input buffers of the current stream, asserting that
at least one of them has state EXECBUF_NEED_PRODUCTION (otherwise the scheduler
is stuck in an infinite loop).  The scheduler then loops back to label
VISIT_VERTEX.

DfsTreeExecStreamScheduler does not support asynchronous runnability
changes (makeRunnable and setTimer).

TBD:  additional assertions; re-entrancy issues for Java XO's.

Example Exec

Putting together the example graph shown earlier with the
DfsTreeExecStreamScheduler algorithm, an example execution trace
might read as follows for a table of five rows:

caller invokes readStreamBuffer() on scheduler with adapter2 as argument.

scheduler calls execute() on adapter2.  adapter2 invokes requestProduction()
on buf3 and calls provideBufferForProduction() with
its allocated cache page.  adapter2 returns EXECRC_NEED_INPUT.

scheduler calls execute() on calc.  calc invokes requestProduction() on
buf2.  calc returns EXECRC_NEED_INPUT.

scheduler calls execute() on adapter1.  adapter1 invokes requestProduction()
on buf1 and calls provideBufferForProduction() with its
allocated cache page.  adapter1 returns EXECRC_NEED_INPUT.

scheduler calls execute() on scan.  scan calls produceData(), writing
five tuples into buf1 and changing its state to EXECBUF_NEED_CONSUMPTION,
and then returns EXECRC_OUTPUT.

scheduler calls execute() on adapter1.  adapter1 calls
provideBufferForConsumption() on buf2, passing it memory references from
buf1 and changing its state to EXECBUF_NEED_CONSUMPTION.
adapter1 returns EXECRC_OUTPUT.

scheduler calls execute() on calc.  calc applies filter and calls
consumeData() to consumes all rows from buf2, changing its state to
EXECBUF_IDLE.
calc writes three rows into buf3, calling produceData() to
set its state to EXECBUF_NEED_CONSUMPTION.  calc returns EXECRC_OUTPUT.

scheduler calls execute() on adapter2.  adapter2 calls
provideBufferForConsumption() on buf4, passing it memory references from
buf3 and changing its state to EXECBUF_NEED_CONSUMPTION.  adapter2 returns
EXECRC_OUTPUT.

scheduler returns to caller with EXECRC_OUTPUT, giving it
a reference to buf4.

caller calls consumeData() to read the data from buf4, changing its state to
EXECBUF_IDLE.

caller invokes readStreamBuffer() on adapter2 again.

scheduler calls execute() on adapter2, which returns EXECRC_NEED_INPUT;
same thing repeats all the way down the tree.

scheduler calls execute() on scan, which calls markEOS() on buf1,
changing its state to EXECBUF_EOS, and returns EXECRC_EOS.

scheduler calls execute() on adapter1, which returns EXECRC_EOS, etc.

scheduler calls execute() on calc, which returns EXECRC_EOS, etc.

scheduler calls execute() on adapter2, which returns EXECRC_EOS, etc.

scheduler returns to caller with EXECRC_EOS.

TODO:  an animated visualization would be more useful.

Note that most real executions will be much more complicated due to
joins and partial consumption of input.

 */
struct SchedulerDesign
{
    // NOTE:  dummy class for doxygen
};

FENNEL_END_CPPFILE("$Id$");

// End SchedulerDesign.cpp
<|endoftext|>


<commit_before>#pragma once

// We use ostream for logging purposes.
#include <iostream>  // NOLINT(readability/streams)
#include <string>

#include "base/not_null.hpp"
#include "geometry/r3_element.hpp"
#include "quantities/quantities.hpp"
#include "serialization/geometry.pb.h"

namespace principia {

using base::not_null;

namespace geometry {

template<typename FromFrame, typename ToFrame> class Permutation;

// A multivector of rank |rank| on a three-dimensional real inner product
// space bearing the dimensionality of |Scalar|, i.e., an element of
// ⋀ⁿ Scalar³. Do not use this type for |rank == 0| (scalars), use the |Scalar|
// type directly instead.
// |Frame| represents a reference frame together with an orthonormal basis.
template<typename Scalar, typename Frame, int rank>
class Multivector;

template<typename Scalar, typename Frame>
class Multivector<Scalar, Frame, 1> {
 public:
  Multivector();
  explicit Multivector(R3Element<Scalar> const& coordinates);
  ~Multivector() = default;

  R3Element<Scalar> const& coordinates() const;
  Scalar Norm() const;

  template<typename S, typename F>
  void Orthogonalize(not_null<Multivector<S, F, 1>*> const multivector) const;

  void WriteToMessage(
      not_null<serialization::Multivector*> const message) const;
  static Multivector ReadFromMessage(serialization::Multivector const& message);

 private:
  R3Element<Scalar> coordinates_;

  template<typename S, typename F, int r>
  friend class Multivector;

  template<typename Scalar, typename Frame, int rank>
  friend Multivector<Scalar, Frame, rank>& operator+=(
      Multivector<Scalar, Frame, rank>& left,  // NOLINT(runtime/references)
      Multivector<Scalar, Frame, rank> const& right);
  template<typename Scalar, typename Frame, int rank>
  friend Multivector<Scalar, Frame, rank>& operator-=(
      Multivector<Scalar, Frame, rank>& left,  // NOLINT(runtime/references)
      Multivector<Scalar, Frame, rank> const& right);
  template<typename Scalar, typename Frame, int rank>
  friend Multivector<Scalar, Frame, rank>& operator*=(
      Multivector<Scalar, Frame, rank>& left,  // NOLINT(runtime/references)
      double const right);
  template<typename Scalar, typename Frame, int rank>
  friend Multivector<Scalar, Frame, rank>& operator/=(
      Multivector<Scalar, Frame, rank>& left,  // NOLINT(runtime/references)
      double const right);
};

template<typename Scalar, typename Frame>
class Multivector<Scalar, Frame, 2> {
 public:
  Multivector();
  explicit Multivector(R3Element<Scalar> const& coordinates);
  ~Multivector() = default;

  R3Element<Scalar> const& coordinates() const;
  Scalar Norm() const;

  template<typename S, typename F>
  void Orthogonalize(not_null<Multivector<S, F, 2>*> const multivector) const;

  void WriteToMessage(
      not_null<serialization::Multivector*> const message) const;
  static Multivector ReadFromMessage(serialization::Multivector const& message);

 private:
  R3Element<Scalar> coordinates_;

  template<typename Scalar, typename Frame, int rank>
  friend Multivector<Scalar, Frame, rank>& operator+=(
      Multivector<Scalar, Frame, rank>& left,  // NOLINT(runtime/references)
      Multivector<Scalar, Frame, rank> const& right);
  template<typename Scalar, typename Frame, int rank>
  friend Multivector<Scalar, Frame, rank>& operator-=(
      Multivector<Scalar, Frame, rank>& left,  // NOLINT(runtime/references)
      Multivector<Scalar, Frame, rank> const& right);
  template<typename Scalar, typename Frame, int rank>
  friend Multivector<Scalar, Frame, rank>& operator*=(
      Multivector<Scalar, Frame, rank>& left,  // NOLINT(runtime/references)
      double const right);
  template<typename Scalar, typename Frame, int rank>
  friend Multivector<Scalar, Frame, rank>& operator/=(
      Multivector<Scalar, Frame, rank>& left,  // NOLINT(runtime/references)
      double const right);
};

template<typename Scalar, typename Frame>
class Multivector<Scalar, Frame, 3> {
 public:
  Multivector();
  explicit Multivector(Scalar const& coordinates);
  ~Multivector() = default;

  Scalar const& coordinates() const;
  Scalar Norm() const;

  void WriteToMessage(
      not_null<serialization::Multivector*> const message) const;
  static Multivector ReadFromMessage(serialization::Multivector const& message);

 private:
  Scalar coordinates_;

  template<typename Scalar, typename Frame, int rank>
  friend Multivector<Scalar, Frame, rank>& operator+=(
      Multivector<Scalar, Frame, rank>& left,  // NOLINT(runtime/references)
      Multivector<Scalar, Frame, rank> const& right);
  template<typename Scalar, typename Frame, int rank>
  friend Multivector<Scalar, Frame, rank>& operator-=(
      Multivector<Scalar, Frame, rank>& left,  // NOLINT(runtime/references)
      Multivector<Scalar, Frame, rank> const& right);
  template<typename Scalar, typename Frame, int rank>
  friend Multivector<Scalar, Frame, rank>& operator*=(
      Multivector<Scalar, Frame, rank>& left,  // NOLINT(runtime/references)
      double const right);
  template<typename Scalar, typename Frame, int rank>
  friend Multivector<Scalar, Frame, rank>& operator/=(
      Multivector<Scalar, Frame, rank>& left,  // NOLINT(runtime/references)
      double const right);
};

template<typename Scalar, typename Frame>
using Vector = Multivector<Scalar, Frame, 1>;
template<typename Scalar, typename Frame>
using Bivector = Multivector<Scalar, Frame, 2>;
template<typename Scalar, typename Frame>
using Trivector = Multivector<Scalar, Frame, 3>;

template<typename LScalar, typename RScalar, typename Frame>
quantities::Product<LScalar, RScalar> InnerProduct(
    Vector<LScalar, Frame> const& left,
    Vector<RScalar, Frame> const& right);
template<typename LScalar, typename RScalar, typename Frame>
quantities::Product<LScalar, RScalar> InnerProduct(
    Bivector<LScalar, Frame> const& left,
    Bivector<RScalar, Frame> const& right);
template<typename LScalar, typename RScalar, typename Frame>
quantities::Product<LScalar, RScalar> InnerProduct(
    Trivector<LScalar, Frame> const& left,
    Trivector<RScalar, Frame> const& right);

template<typename LScalar, typename RScalar, typename Frame>
Bivector<quantities::Product<LScalar, RScalar>, Frame> Wedge(
    Vector<LScalar, Frame> const& left,
    Vector<RScalar, Frame> const& right);
template<typename LScalar, typename RScalar, typename Frame>
Trivector<quantities::Product<LScalar, RScalar>, Frame> Wedge(
    Bivector<LScalar, Frame> const& left,
    Vector<RScalar, Frame> const& right);
template<typename LScalar, typename RScalar, typename Frame>
Trivector<quantities::Product<LScalar, RScalar>, Frame> Wedge(
    Vector<LScalar, Frame> const& left,
    Bivector<RScalar, Frame> const& right);

// Lie bracket on 𝑉 ∧ 𝑉 ≅ 𝖘𝔬(𝑉).
template<typename LScalar, typename RScalar, typename Frame>
Bivector<quantities::Product<LScalar, RScalar>, Frame> Commutator(
    Bivector<LScalar, Frame> const& left,
    Bivector<RScalar, Frame> const& right);

// Returns multivector / ‖multivector‖.
template<typename Scalar, typename Frame, int rank>
Multivector<double, Frame, rank> Normalize(
    Multivector<Scalar, Frame, rank> const& multivector);

// Left action of 𝑉 ∧ 𝑉 ≅ 𝖘𝔬(𝑉) on 𝑉.
template<typename LScalar, typename RScalar, typename Frame>
Vector<quantities::Product<LScalar, RScalar>, Frame> operator*(
    Bivector<LScalar, Frame> const& left,
    Vector<RScalar, Frame> const& right);

// Right action of 𝑉 ∧ 𝑉 ≅ 𝖘𝔬(𝑉) on 𝑉* ≅ 𝑉.
template<typename LScalar, typename RScalar, typename Frame>
Vector<quantities::Product<LScalar, RScalar>, Frame> operator*(
    Vector<LScalar, Frame> const& left,
    Bivector<RScalar, Frame> const& right);

template<typename FromFrame, typename ToFrame> class Rotation;

// Exponential map 𝑉 ∧ 𝑉 ≅ 𝖘𝔬(𝑉) → SO(𝑉).
template<typename Frame>
Rotation<Frame, Frame> Exp(Bivector<quantities::Angle, Frame> const& exponent);

template<typename LScalar, typename RScalar, typename Frame>
Vector<quantities::Product<LScalar, RScalar>, Frame> operator*(
    Bivector<LScalar, Frame> const& left,
    Trivector<RScalar, Frame> const& right);
template<typename LScalar, typename RScalar, typename Frame>
Vector<quantities::Product<LScalar, RScalar>, Frame> operator*(
    Trivector<LScalar, Frame> const& left,
    Bivector<RScalar, Frame> const& right);
template<typename LScalar, typename RScalar, typename Frame>
Bivector<quantities::Product<LScalar, RScalar>, Frame> operator*(
    Vector<LScalar, Frame> const& left,
    Trivector<RScalar, Frame> const& right);
template<typename LScalar, typename RScalar, typename Frame>
Bivector<quantities::Product<LScalar, RScalar>, Frame> operator*(
    Trivector<LScalar, Frame> const& left,
    Vector<RScalar, Frame> const& right);

template<typename Scalar, typename Frame, int rank>
Multivector<Scalar, Frame, rank> operator+(
    Multivector<Scalar, Frame, rank> const& right);
template<typename Scalar, typename Frame, int rank>
Multivector<Scalar, Frame, rank> operator-(
    Multivector<Scalar, Frame, rank> const& right);

template<typename Scalar, typename Frame, int rank>
Multivector<Scalar, Frame, rank> operator+(
    Multivector<Scalar, Frame, rank> const& left,
    Multivector<Scalar, Frame, rank> const& right);
template<typename Scalar, typename Frame, int rank>
Multivector<Scalar, Frame, rank> operator-(
    Multivector<Scalar, Frame, rank> const& left,
    Multivector<Scalar, Frame, rank> const& right);

template<typename Scalar, typename Frame, int rank>
Multivector<Scalar, Frame, rank> operator*(
    double const left,
    Multivector<Scalar, Frame, rank> const& right);
template<typename Scalar, typename Frame, int rank>
Multivector<Scalar, Frame, rank> operator*(
    Multivector<Scalar, Frame, rank> const& left,
    double const right);
template<typename Scalar, typename Frame, int rank>
Multivector<Scalar, Frame, rank> operator/(
    Multivector<Scalar, Frame, rank> const& left,
    double const right);

template<typename LDimension, typename RScalar, typename Frame, int rank>
Multivector<quantities::Product<quantities::Quantity<LDimension>, RScalar>,
            Frame, rank>
operator*(quantities::Quantity<LDimension> const& left,
          Multivector<RScalar, Frame, rank> const& right);

template<typename LScalar, typename RDimension, typename Frame, int rank>
Multivector<quantities::Product<LScalar, quantities::Quantity<RDimension>>,
            Frame, rank>
operator*(Multivector<LScalar, Frame, rank> const& left,
          quantities::Quantity<RDimension> const& right);

template<typename LScalar, typename RDimension, typename Frame, int rank>
Multivector<quantities::Quotient<LScalar, quantities::Quantity<RDimension>>,
            Frame, rank>
operator/(Multivector<LScalar, Frame, rank> const& left,
          quantities::Quantity<RDimension> const& right);

template<typename Scalar, typename Frame, int rank>
bool operator==(Multivector<Scalar, Frame, rank> const& left,
                Multivector<Scalar, Frame, rank> const& right);
template<typename Scalar, typename Frame, int rank>
bool operator!=(Multivector<Scalar, Frame, rank> const& left,
                Multivector<Scalar, Frame, rank> const& right);

template<typename Scalar, typename Frame, int rank>
Multivector<Scalar, Frame, rank>& operator+=(
    Multivector<Scalar, Frame, rank>& left,  // NOLINT(runtime/references)
    Multivector<Scalar, Frame, rank> const& right);
template<typename Scalar, typename Frame, int rank>
Multivector<Scalar, Frame, rank>& operator-=(
    Multivector<Scalar, Frame, rank>& left,  // NOLINT(runtime/references)
    Multivector<Scalar, Frame, rank> const& right);
template<typename Scalar, typename Frame, int rank>
Multivector<Scalar, Frame, rank>& operator*=(
    Multivector<Scalar, Frame, rank>& left,  // NOLINT(runtime/references)
    double const right);
template<typename Scalar, typename Frame, int rank>
Multivector<Scalar, Frame, rank>& operator/=(
    Multivector<Scalar, Frame, rank>& left,  // NOLINT(runtime/references)
    double const right);

template<typename Scalar, typename Frame, int rank>
std::string DebugString(Multivector<Scalar, Frame, rank> const& multivector);

template<typename Scalar, typename Frame, int rank>
std::ostream& operator<<(std::ostream& out,
                         Multivector<Scalar, Frame, rank> const& multivector);

}  // namespace geometry
}  // namespace principia

#include "geometry/grassmann_body.hpp"
<commit_msg>Fix template shadowing<commit_after>#pragma once

// We use ostream for logging purposes.
#include <iostream>  // NOLINT(readability/streams)
#include <string>

#include "base/not_null.hpp"
#include "geometry/r3_element.hpp"
#include "quantities/quantities.hpp"
#include "serialization/geometry.pb.h"

namespace principia {

using base::not_null;

namespace geometry {

template<typename FromFrame, typename ToFrame> class Permutation;

// A multivector of rank |rank| on a three-dimensional real inner product
// space bearing the dimensionality of |Scalar|, i.e., an element of
// ⋀ⁿ Scalar³. Do not use this type for |rank == 0| (scalars), use the |Scalar|
// type directly instead.
// |Frame| represents a reference frame together with an orthonormal basis.
template<typename Scalar, typename Frame, int rank>
class Multivector;

template<typename Scalar, typename Frame>
class Multivector<Scalar, Frame, 1> {
 public:
  Multivector();
  explicit Multivector(R3Element<Scalar> const& coordinates);
  ~Multivector() = default;

  R3Element<Scalar> const& coordinates() const;
  Scalar Norm() const;

  template<typename S, typename F>
  void Orthogonalize(not_null<Multivector<S, F, 1>*> const multivector) const;

  void WriteToMessage(
      not_null<serialization::Multivector*> const message) const;
  static Multivector ReadFromMessage(serialization::Multivector const& message);

 private:
  R3Element<Scalar> coordinates_;

  template<typename S, typename F, int r>
  friend class Multivector;

  template<typename S, typename F, int r>
  friend Multivector<S, F, r>& operator+=(
      Multivector<S, F, r>& left,  // NOLINT(runtime/references)
      Multivector<S, F, r> const& right);
  template<typename S, typename F, int r>
  friend Multivector<S, F, r>& operator-=(
      Multivector<S, F, r>& left,  // NOLINT(runtime/references)
      Multivector<S, F, r> const& right);
  template<typename S, typename F, int r>
  friend Multivector<S, F, r>& operator*=(
      Multivector<S, F, r>& left,  // NOLINT(runtime/references)
      double const right);
  template<typename S, typename F, int r>
  friend Multivector<S, F, r>& operator/=(
      Multivector<S, F, r>& left,  // NOLINT(runtime/references)
      double const right);
};

template<typename Scalar, typename Frame>
class Multivector<Scalar, Frame, 2> {
 public:
  Multivector();
  explicit Multivector(R3Element<Scalar> const& coordinates);
  ~Multivector() = default;

  R3Element<Scalar> const& coordinates() const;
  Scalar Norm() const;

  template<typename S, typename F>
  void Orthogonalize(not_null<Multivector<S, F, 2>*> const multivector) const;

  void WriteToMessage(
      not_null<serialization::Multivector*> const message) const;
  static Multivector ReadFromMessage(serialization::Multivector const& message);

 private:
  R3Element<Scalar> coordinates_;

  template<typename S, typename F, int r>
  friend Multivector<S, F, r>& operator+=(
      Multivector<S, F, r>& left,  // NOLINT(runtime/references)
      Multivector<S, F, r> const& right);
  template<typename S, typename F, int r>
  friend Multivector<S, F, r>& operator-=(
      Multivector<S, F, r>& left,  // NOLINT(runtime/references)
      Multivector<S, F, r> const& right);
  template<typename S, typename F, int r>
  friend Multivector<S, F, r>& operator*=(
      Multivector<S, F, r>& left,  // NOLINT(runtime/references)
      double const right);
  template<typename S, typename F, int r>
  friend Multivector<S, F, r>& operator/=(
      Multivector<S, F, r>& left,  // NOLINT(runtime/references)
      double const right);
};

template<typename Scalar, typename Frame>
class Multivector<Scalar, Frame, 3> {
 public:
  Multivector();
  explicit Multivector(Scalar const& coordinates);
  ~Multivector() = default;

  Scalar const& coordinates() const;
  Scalar Norm() const;

  void WriteToMessage(
      not_null<serialization::Multivector*> const message) const;
  static Multivector ReadFromMessage(serialization::Multivector const& message);

 private:
  Scalar coordinates_;

  template<typename S, typename F, int r>
  friend Multivector<S, F, r>& operator+=(
      Multivector<S, F, r>& left,  // NOLINT(runtime/references)
      Multivector<S, F, r> const& right);
  template<typename S, typename F, int r>
  friend Multivector<S, F, r>& operator-=(
      Multivector<S, F, r>& left,  // NOLINT(runtime/references)
      Multivector<S, F, r> const& right);
  template<typename S, typename F, int r>
  friend Multivector<S, F, r>& operator*=(
      Multivector<S, F, r>& left,  // NOLINT(runtime/references)
      double const right);
  template<typename S, typename F, int r>
  friend Multivector<S, F, r>& operator/=(
      Multivector<S, F, r>& left,  // NOLINT(runtime/references)
      double const right);
};

template<typename Scalar, typename Frame>
using Vector = Multivector<Scalar, Frame, 1>;
template<typename Scalar, typename Frame>
using Bivector = Multivector<Scalar, Frame, 2>;
template<typename Scalar, typename Frame>
using Trivector = Multivector<Scalar, Frame, 3>;

template<typename LScalar, typename RScalar, typename Frame>
quantities::Product<LScalar, RScalar> InnerProduct(
    Vector<LScalar, Frame> const& left,
    Vector<RScalar, Frame> const& right);
template<typename LScalar, typename RScalar, typename Frame>
quantities::Product<LScalar, RScalar> InnerProduct(
    Bivector<LScalar, Frame> const& left,
    Bivector<RScalar, Frame> const& right);
template<typename LScalar, typename RScalar, typename Frame>
quantities::Product<LScalar, RScalar> InnerProduct(
    Trivector<LScalar, Frame> const& left,
    Trivector<RScalar, Frame> const& right);

template<typename LScalar, typename RScalar, typename Frame>
Bivector<quantities::Product<LScalar, RScalar>, Frame> Wedge(
    Vector<LScalar, Frame> const& left,
    Vector<RScalar, Frame> const& right);
template<typename LScalar, typename RScalar, typename Frame>
Trivector<quantities::Product<LScalar, RScalar>, Frame> Wedge(
    Bivector<LScalar, Frame> const& left,
    Vector<RScalar, Frame> const& right);
template<typename LScalar, typename RScalar, typename Frame>
Trivector<quantities::Product<LScalar, RScalar>, Frame> Wedge(
    Vector<LScalar, Frame> const& left,
    Bivector<RScalar, Frame> const& right);

// Lie bracket on 𝑉 ∧ 𝑉 ≅ 𝖘𝔬(𝑉).
template<typename LScalar, typename RScalar, typename Frame>
Bivector<quantities::Product<LScalar, RScalar>, Frame> Commutator(
    Bivector<LScalar, Frame> const& left,
    Bivector<RScalar, Frame> const& right);

// Returns multivector / ‖multivector‖.
template<typename Scalar, typename Frame, int rank>
Multivector<double, Frame, rank> Normalize(
    Multivector<Scalar, Frame, rank> const& multivector);

// Left action of 𝑉 ∧ 𝑉 ≅ 𝖘𝔬(𝑉) on 𝑉.
template<typename LScalar, typename RScalar, typename Frame>
Vector<quantities::Product<LScalar, RScalar>, Frame> operator*(
    Bivector<LScalar, Frame> const& left,
    Vector<RScalar, Frame> const& right);

// Right action of 𝑉 ∧ 𝑉 ≅ 𝖘𝔬(𝑉) on 𝑉* ≅ 𝑉.
template<typename LScalar, typename RScalar, typename Frame>
Vector<quantities::Product<LScalar, RScalar>, Frame> operator*(
    Vector<LScalar, Frame> const& left,
    Bivector<RScalar, Frame> const& right);

template<typename FromFrame, typename ToFrame> class Rotation;

// Exponential map 𝑉 ∧ 𝑉 ≅ 𝖘𝔬(𝑉) → SO(𝑉).
template<typename Frame>
Rotation<Frame, Frame> Exp(Bivector<quantities::Angle, Frame> const& exponent);

template<typename LScalar, typename RScalar, typename Frame>
Vector<quantities::Product<LScalar, RScalar>, Frame> operator*(
    Bivector<LScalar, Frame> const& left,
    Trivector<RScalar, Frame> const& right);
template<typename LScalar, typename RScalar, typename Frame>
Vector<quantities::Product<LScalar, RScalar>, Frame> operator*(
    Trivector<LScalar, Frame> const& left,
    Bivector<RScalar, Frame> const& right);
template<typename LScalar, typename RScalar, typename Frame>
Bivector<quantities::Product<LScalar, RScalar>, Frame> operator*(
    Vector<LScalar, Frame> const& left,
    Trivector<RScalar, Frame> const& right);
template<typename LScalar, typename RScalar, typename Frame>
Bivector<quantities::Product<LScalar, RScalar>, Frame> operator*(
    Trivector<LScalar, Frame> const& left,
    Vector<RScalar, Frame> const& right);

template<typename Scalar, typename Frame, int rank>
Multivector<Scalar, Frame, rank> operator+(
    Multivector<Scalar, Frame, rank> const& right);
template<typename Scalar, typename Frame, int rank>
Multivector<Scalar, Frame, rank> operator-(
    Multivector<Scalar, Frame, rank> const& right);

template<typename Scalar, typename Frame, int rank>
Multivector<Scalar, Frame, rank> operator+(
    Multivector<Scalar, Frame, rank> const& left,
    Multivector<Scalar, Frame, rank> const& right);
template<typename Scalar, typename Frame, int rank>
Multivector<Scalar, Frame, rank> operator-(
    Multivector<Scalar, Frame, rank> const& left,
    Multivector<Scalar, Frame, rank> const& right);

template<typename Scalar, typename Frame, int rank>
Multivector<Scalar, Frame, rank> operator*(
    double const left,
    Multivector<Scalar, Frame, rank> const& right);
template<typename Scalar, typename Frame, int rank>
Multivector<Scalar, Frame, rank> operator*(
    Multivector<Scalar, Frame, rank> const& left,
    double const right);
template<typename Scalar, typename Frame, int rank>
Multivector<Scalar, Frame, rank> operator/(
    Multivector<Scalar, Frame, rank> const& left,
    double const right);

template<typename LDimension, typename RScalar, typename Frame, int rank>
Multivector<quantities::Product<quantities::Quantity<LDimension>, RScalar>,
            Frame, rank>
operator*(quantities::Quantity<LDimension> const& left,
          Multivector<RScalar, Frame, rank> const& right);

template<typename LScalar, typename RDimension, typename Frame, int rank>
Multivector<quantities::Product<LScalar, quantities::Quantity<RDimension>>,
            Frame, rank>
operator*(Multivector<LScalar, Frame, rank> const& left,
          quantities::Quantity<RDimension> const& right);

template<typename LScalar, typename RDimension, typename Frame, int rank>
Multivector<quantities::Quotient<LScalar, quantities::Quantity<RDimension>>,
            Frame, rank>
operator/(Multivector<LScalar, Frame, rank> const& left,
          quantities::Quantity<RDimension> const& right);

template<typename Scalar, typename Frame, int rank>
bool operator==(Multivector<Scalar, Frame, rank> const& left,
                Multivector<Scalar, Frame, rank> const& right);
template<typename Scalar, typename Frame, int rank>
bool operator!=(Multivector<Scalar, Frame, rank> const& left,
                Multivector<Scalar, Frame, rank> const& right);

template<typename Scalar, typename Frame, int rank>
Multivector<Scalar, Frame, rank>& operator+=(
    Multivector<Scalar, Frame, rank>& left,  // NOLINT(runtime/references)
    Multivector<Scalar, Frame, rank> const& right);
template<typename Scalar, typename Frame, int rank>
Multivector<Scalar, Frame, rank>& operator-=(
    Multivector<Scalar, Frame, rank>& left,  // NOLINT(runtime/references)
    Multivector<Scalar, Frame, rank> const& right);
template<typename Scalar, typename Frame, int rank>
Multivector<Scalar, Frame, rank>& operator*=(
    Multivector<Scalar, Frame, rank>& left,  // NOLINT(runtime/references)
    double const right);
template<typename Scalar, typename Frame, int rank>
Multivector<Scalar, Frame, rank>& operator/=(
    Multivector<Scalar, Frame, rank>& left,  // NOLINT(runtime/references)
    double const right);

template<typename Scalar, typename Frame, int rank>
std::string DebugString(Multivector<Scalar, Frame, rank> const& multivector);

template<typename Scalar, typename Frame, int rank>
std::ostream& operator<<(std::ostream& out,
                         Multivector<Scalar, Frame, rank> const& multivector);

}  // namespace geometry
}  // namespace principia

#include "geometry/grassmann_body.hpp"
<|endoftext|>


<commit_before>// This is the main file for all unit tests using CATCH.
//
// The tests are compiled and executed with "make check", further tests can be
// added in src/Makefile.am.
//
// See also: https://github.com/philsquared/Catch/wiki/Tutorial

#define CATCH_CONFIG_MAIN
#include "catch/catch.hpp"
<commit_msg>Update comments in main.cpp<commit_after>// This is the main file for all unit tests using CATCH.
//
// The tests are compiled and executed with "make", further tests can be
// added in the Makefile.
//
// See also: https://github.com/philsquared/Catch/blob/master/docs/tutorial.md

#define CATCH_CONFIG_MAIN
#include "catch/catch.hpp"
<|endoftext|>


<commit_before>/*
This file is part of Bohrium and copyright (c) 2012 the Bohrium
team <http://www.bh107.org>.

Bohrium 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 3
of the License, or (at your option) any later version.

Bohrium 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 Lesser General Public License along with Bohrium.

If not, see <http://www.gnu.org/licenses/>.
*/
#include <bh.h>
#include <stdio.h>
#include <bh_dag.h>

using namespace std;
using namespace boost;
using namespace bohrium::dag;

static int filter_count=0;
void filter(const bh_ir &bhir)
{
    GraphDW dag;
    char filename[8000];

    snprintf(filename, 8000, "dag-%d.dot", ++filter_count);
    printf("fuseprinter: writing dag('%s').\n", filename);

    from_kernels(bhir.kernel_list, dag);
    pprint(dag, filename);
}
<commit_msg>fuseprinter: will now also print subgraphs<commit_after>/*
This file is part of Bohrium and copyright (c) 2012 the Bohrium
team <http://www.bh107.org>.

Bohrium 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 3
of the License, or (at your option) any later version.

Bohrium 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 Lesser General Public License along with Bohrium.

If not, see <http://www.gnu.org/licenses/>.
*/
#include <bh.h>
#include <stdio.h>
#include <bh_dag.h>

using namespace std;
using namespace boost;
using namespace bohrium::dag;

static int filter_count=1;
void filter(const bh_ir &bhir)
{
    GraphDW dag;

    from_kernels(bhir.kernel_list, dag);
    vector<GraphDW> dags;
    split(dag, dags);
    int i=0;
    BOOST_FOREACH(GraphDW &d, dags)
    {
        char filename[8000];
        snprintf(filename, 8000, "dag-%d-%d.dot", filter_count, ++i);
        pprint(d, filename);
    }
    char filename[8000];
    snprintf(filename, 8000, "dag-%d.dot", filter_count++);
    printf("fuseprinter: writing dag('%s').\n", filename);
    pprint(dag, filename);
}
<|endoftext|>


<commit_before>#include <FarPluginBase.h>
#ifdef _DEBUG
#include <debug.h>
#endif
#include "wcx.class.h"

int __stdcall WcxArchive::ProcessDataProc (char *FileName, int Size)
{
	if ( m_pfnCallback )
		return m_pfnCallback (AM_PROCESS_DATA, 0, (int)Size);

	return 1;
}

int __stdcall WcxArchive::SetChangeVolProc (char *ArcName, int Mode)
{
	return 1;
}

WcxModule::WcxModule (const char *lpFileName)
{
	m_hModule = LoadLibraryEx (
			lpFileName,
			NULL,
			LOAD_WITH_ALTERED_SEARCH_PATH
			);

	if ( m_hModule )
	{
		m_pfnOpenArchive=(PLUGINOPENARCHIVE)GetProcAddress(m_hModule,"OpenArchive");
		m_pfnCloseArchive=(PLUGINCLOSEARCHIVE)GetProcAddress(m_hModule,"CloseArchive");
		m_pfnReadHeader=(PLUGINREADHEADER)GetProcAddress(m_hModule,"ReadHeader");
		m_pfnProcessFile=(PLUGINPROCESSFILE)GetProcAddress(m_hModule,"ProcessFile");
		m_pfnPackFiles=(PLUGINPACKFILES)GetProcAddress(m_hModule,"PackFiles");
		m_pfnDeleteFiles=(PLUGINDELETEFILES)GetProcAddress(m_hModule,"DeleteFiles");
		m_pfnSetChangeVolProc=(PLUGINSETCHANGEVOLPROC)GetProcAddress(m_hModule,"SetChangeVolProc");
		m_pfnSetProcessDataProc=(PLUGINSETPROCESSDATAPROC)GetProcAddress(m_hModule,"SetProcessDataProc");
		m_pfnConfigurePacker=(PLUGINCONFIGUREPACKER)GetProcAddress(m_hModule,"ConfigurePacker");
		m_pfnGetPackerCaps=(PLUGINGETPACKERCAPS)GetProcAddress(m_hModule,"GetPackerCaps");
		m_pfnCanYouHandleThisFile=(PLUGINCANYOUHANDLETHISFILE)GetProcAddress(m_hModule,"CanYouHandleThisFile");
		m_pfnPackSetDefaultParams=(PLUGINPACKSETDEFAULTPARAMS)GetProcAddress(m_hModule,"PackSetDefaultParams");
	}

	if ( LoadedOK() )
	{
		if (m_pfnPackSetDefaultParams)
		{
			PackDefaultParamStruct dps;

			dps.size = sizeof(dps);
			dps.PluginInterfaceVersionLow = 10;
			dps.PluginInterfaceVersionHi = 2;
			strcpy(dps.DefaultIniName,"");

			m_pfnPackSetDefaultParams(&dps);
		}
	}
}

bool WcxModule::LoadedOK ()
{
	if ( !(m_hModule && m_pfnOpenArchive && m_pfnCloseArchive && m_pfnReadHeader && m_pfnProcessFile) )
		return false;

	return true;
}

WcxModule::~WcxModule ()
{
	FreeLibrary (m_hModule);
}

WcxModules::WcxModules ()
{
	memset (&m_PluginInfo, 0, sizeof (m_PluginInfo));

	char *lpPluginsPath = StrDuplicate (Info.ModuleName, 260);

	CutToSlash (lpPluginsPath);

	strcat (lpPluginsPath, "Formats");

	m_Modules.Create(10);
	m_ExtraPluginInfo.Create(10);

	FSF.FarRecursiveSearch(lpPluginsPath,"*.wcx",(FRSUSERFUNC)LoadWcxModules,FRS_RECUR,this);

	StrFree(lpPluginsPath);

	m_PluginInfo.pFormatInfo = (ArchiveFormatInfo *) realloc (m_PluginInfo.pFormatInfo, sizeof (ArchiveFormatInfo) * m_PluginInfo.nFormats);

	for (int i=0; i<m_ExtraPluginInfo.GetCount (); i++)
	{
		m_PluginInfo.pFormatInfo[i].dwFlags = AFF_SUPPORT_INTERNAL_EXTRACT|AFF_SUPPORT_INTERNAL_TEST;
		m_PluginInfo.pFormatInfo[i].lpName = m_ExtraPluginInfo[i]->Name;
		m_PluginInfo.pFormatInfo[i].lpDefaultExtention = m_ExtraPluginInfo[i]->DefaultExtention;
	}
}

WcxModules::~WcxModules ()
{
	if ( m_PluginInfo.pFormatInfo )
		free (m_PluginInfo.pFormatInfo);

	m_ExtraPluginInfo.Free ();
	m_Modules.Free ();
}

WcxModule *WcxModules::IsArchive (QueryArchiveStruct *pQAS, int *nModuleNum)
{
	WcxModule *TrueArc = NULL;

    *nModuleNum = -1;

	for (int i=0; i<m_Modules.GetCount(); i++)
	{
		if ( m_Modules[i]->m_pfnCanYouHandleThisFile )
		{
			if (m_Modules[i]->m_pfnCanYouHandleThisFile (pQAS->lpFileName))
			{
				TrueArc = m_Modules[i];
				*nModuleNum = i;
				break;
			}
		}
		else
		{
			tOpenArchiveData OpenArchiveData = {0};

			OpenArchiveData.ArcName = (char *)pQAS->lpFileName;
			OpenArchiveData.OpenMode = PK_OM_LIST;

			HANDLE hArchive = m_Modules[i]->m_pfnOpenArchive (&OpenArchiveData);

			if (hArchive)
			{
				m_Modules[i]->m_pfnCloseArchive (hArchive);
				TrueArc = m_Modules[i];
				*nModuleNum = i;
				break;
			}
		}
	}

	return TrueArc;
}

int WINAPI WcxModules::LoadWcxModules (const WIN32_FIND_DATA *pFindData,
		const char *lpFullName,
		WcxModules *pModules
		)
{
	if ( pFindData->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
		return TRUE;

	WcxModule *pModule = new WcxModule (lpFullName);

	if ( !pModule )
		return TRUE;

	if ( !pModule->LoadedOK () )
	{
		delete pModule;
		return TRUE;
	}

    pModules->m_PluginInfo.nFormats++;

    ExtraPluginInfo *pExtraPluginInfo = (ExtraPluginInfo *) malloc (sizeof (ExtraPluginInfo));

	strcpy(pExtraPluginInfo->Name,FSF.PointToName(lpFullName));
	*strrchr(pExtraPluginInfo->Name,'.') = 0;
	strcpy(pExtraPluginInfo->DefaultExtention,pExtraPluginInfo->Name);
	strcat(pExtraPluginInfo->Name," [wcx]");

	pModules->m_ExtraPluginInfo.Add (pExtraPluginInfo);
	pModules->m_Modules.Add (pModule);

	return TRUE;
}

void WcxModules::GetArchivePluginInfo (ArchivePluginInfo *ai)
{
	ai->nFormats = m_PluginInfo.nFormats;
	ai->pFormatInfo = m_PluginInfo.pFormatInfo;
}

bool WcxModules::GetDefaultCommand (int nFormat, int nCommand, char *lpCommand)
{
	return false;
}

WcxArchive::WcxArchive (WcxModule *pModule, int nModuleNum, const char *lpFileName)
{
	m_pModule = pModule;

	m_lpFileName = StrDuplicate (lpFileName);

	m_nModuleNum = nModuleNum;

	m_hArchive = NULL;

	CreateClassThunk (WcxArchive, ProcessDataProc, m_pfnProcessDataProc);
	CreateClassThunk (WcxArchive, SetChangeVolProc, m_pfnSetChangeVolProc);

	m_pfnCallback = NULL;
}

WcxArchive::~WcxArchive ()
{
	StrFree (m_lpFileName);

	free (m_pfnProcessDataProc);
	free (m_pfnSetChangeVolProc);
}

int WcxArchive::ConvertResult (int nResult)
{
	switch (nResult)
	{
		case E_END_ARCHIVE:
			return E_EOF;
		case E_BAD_ARCHIVE:
			return E_BROKEN;
		case E_BAD_DATA:
			return E_UNEXPECTED_EOF;
		case E_EREAD:
			return E_READ_ERROR;
	}

	return E_UNEXPECTED_EOF;
}

bool __stdcall WcxArchive::pOpenArchive (int nOpMode, ARCHIVECALLBACK pfnCallback)
{
	m_pfnCallback = pfnCallback;

	tOpenArchiveData OpenArchiveData = {0};

	OpenArchiveData.ArcName = m_lpFileName;
	OpenArchiveData.OpenMode = (nOpMode == OM_EXTRACT)?PK_OM_EXTRACT:PK_OM_LIST;

	m_hArchive = m_pModule->m_pfnOpenArchive (&OpenArchiveData);

	if ( m_hArchive )
	{
		if (m_pModule->m_pfnSetProcessDataProc)
			m_pModule->m_pfnSetProcessDataProc (m_hArchive, (tProcessDataProc)m_pfnProcessDataProc);

		if (m_pModule->m_pfnSetChangeVolProc)
			m_pModule->m_pfnSetChangeVolProc (m_hArchive, (tChangeVolProc)m_pfnSetChangeVolProc);

		return true;
	}

	return false;
}

void __stdcall WcxArchive::pCloseArchive ()
{
	m_pModule->m_pfnCloseArchive (m_hArchive);
}

int __stdcall WcxArchive::pGetArchiveItem (ArchiveItemInfo *pItem)
{
	int nResult = 0;

	//__debug ("%d", m_hArchive);

/*	if (!m_hArchive)
	{
		tOpenArchiveData OpenArchiveData = {0};

		OpenArchiveData.ArcName = m_lpFileName;
		OpenArchiveData.OpenMode = PK_OM_LIST;

		m_hArchive = m_pModule->m_pfnOpenArchive (&OpenArchiveData);

		if (m_hArchive)
		{
			if (m_pModule->m_pfnSetProcessDataProc)
				m_pModule->m_pfnSetProcessDataProc (m_hArchive, ProcessDataProc);
			if (m_pModule->m_pfnSetChangeVolProc)
				m_pModule->m_pfnSetChangeVolProc (m_hArchive, SetChangeVolProc);
		}
	}
	else        */
	//{
		//nResult = m_pModule->m_pfnProcessFile (m_hArchive, PK_SKIP, NULL, NULL);
	//}

	//if (m_hArchive)
	{
		if (!nResult)
		{
			tHeaderData HeaderData;
			memset (&HeaderData, 0, sizeof (HeaderData));
			//strcpy (HeaderData.ArcName, m_lpFileName);

			nResult = m_pModule->m_pfnReadHeader (m_hArchive, &HeaderData);

			m_pModule->m_pfnProcessFile (m_hArchive, PK_SKIP, NULL, NULL);

			if ( !nResult )
			{
				CharToOem(HeaderData.FileName,pItem->pi.FindData.cFileName);

				pItem->pi.FindData.dwFileAttributes = HeaderData.FileAttr;
				pItem->pi.FindData.nFileSizeLow = HeaderData.UnpSize;

				FILETIME filetime;
				DosDateTimeToFileTime ((WORD)((DWORD)HeaderData.FileTime >> 16), (WORD)HeaderData.FileTime, &filetime);
				LocalFileTimeToFileTime (&filetime, &pItem->pi.FindData.ftLastWriteTime);
				pItem->pi.FindData.ftCreationTime = pItem->pi.FindData.ftLastAccessTime = pItem->pi.FindData.ftLastWriteTime;

				pItem->pi.PackSize = HeaderData.PackSize;
				pItem->pi.CRC32 = HeaderData.FileCRC;

				return E_SUCCESS;
			}

		}

	//	m_pModule->m_pfnCloseArchive (m_hArchive);
	//	m_hArchive = NULL;
	}

	return ConvertResult (nResult);
}

int __stdcall WcxArchive::pGetArchiveType ()
{
	return (m_nModuleNum);
}

bool __stdcall WcxArchive::pExtract (
		PluginPanelItem *pItems,
		int nItemsNumber,
		const char *lpDestPath,
		const char *lpCurrentFolder
		)
{
	int nProcessed = 0;
	int nResult = 0;

	bool bFound;

	char *lpDestName = StrCreate (260);
	char *lpTemp = StrCreate (260);

	/*if (!m_hArchive)
	{
		tOpenArchiveData OpenArchiveData = {0};

		OpenArchiveData.ArcName = m_lpFileName;
		OpenArchiveData.OpenMode = PK_OM_EXTRACT;

		m_hArchive = m_pModule->m_pfnOpenArchive (&OpenArchiveData);

		if (m_hArchive)
		{
			if (m_pModule->m_pfnSetProcessDataProc)
				m_pModule->m_pfnSetProcessDataProc (m_hArchive, m_pfnProcessDataProc);
			if (m_pModule->m_pfnSetChangeVolProc)
				m_pModule->m_pfnSetChangeVolProc (m_hArchive, m_pfnSetChangeVolProc);
		}
	}*/

	while ( /*m_hArchive &&*/ nResult == 0 )
	{
		tHeaderData HeaderData;
		memset (&HeaderData, 0, sizeof (HeaderData));

		nResult = m_pModule->m_pfnReadHeader (m_hArchive, &HeaderData);

		if ( nResult == 0 )
		{
			CharToOem (HeaderData.FileName, lpTemp);

			bFound = false;

			int i = 0;

			for (; i < nItemsNumber; i++)
			{
				if ( !strcmp (pItems[i].FindData.cFileName, lpTemp) )
				{
					OemToChar (lpDestPath, lpDestName);

					FSF.AddEndSlash (lpDestName);

					char *lpName = HeaderData.FileName;

					if ( *lpCurrentFolder /*&& !strncmp (
							lpName,
							lpCurrentFolder,
							strlen (lpCurrentFolder)
							)*/ )
						lpName += strlen (lpCurrentFolder);

					if ( *lpName == '\\' )
						lpName++;

					strcat (lpDestName, lpName);

					if ( m_pfnCallback )
						m_pfnCallback (AM_START_EXTRACT_FILE, (int)&pItems[i], (int)lpDestName);

					int nProcessResult = m_pModule->m_pfnProcessFile (m_hArchive, PK_EXTRACT, NULL, lpDestName);

					if ( !nProcessResult )
						nProcessed++;

					if ( /*m_bAborted ||*/ nProcessResult || (nProcessed == nItemsNumber) )
						goto l_1;

					bFound = true;

					break;
				}
			}

			if ( !bFound )
				m_pModule->m_pfnProcessFile (m_hArchive, PK_SKIP, NULL, NULL);
		}
	}

l_1:

/*	if (m_hArchive)
	{
		m_pModule->m_pfnCloseArchive (m_hArchive);
		m_hArchive = NULL;
	}*/

	//m_bAborted = false;

	StrFree (lpDestName);
	StrFree (lpTemp);

	return nProcessed!=0;
}
<commit_msg>small update<commit_after>#include <FarPluginBase.h>
#ifdef _DEBUG
#include <debug.h>
#endif
#include "wcx.class.h"

int __stdcall WcxArchive::ProcessDataProc (char *FileName, int Size)
{
	if ( m_pfnCallback )
		return m_pfnCallback (AM_PROCESS_DATA, 0, (int)Size);

	return 1;
}

int __stdcall WcxArchive::SetChangeVolProc (char *ArcName, int Mode)
{
	return 1;
}

WcxModule::WcxModule (const char *lpFileName)
{
	m_hModule = LoadLibraryEx (
			lpFileName,
			NULL,
			LOAD_WITH_ALTERED_SEARCH_PATH
			);

	if ( m_hModule )
	{
		m_pfnOpenArchive=(PLUGINOPENARCHIVE)GetProcAddress(m_hModule,"OpenArchive");
		m_pfnCloseArchive=(PLUGINCLOSEARCHIVE)GetProcAddress(m_hModule,"CloseArchive");
		m_pfnReadHeader=(PLUGINREADHEADER)GetProcAddress(m_hModule,"ReadHeader");
		m_pfnProcessFile=(PLUGINPROCESSFILE)GetProcAddress(m_hModule,"ProcessFile");
		m_pfnPackFiles=(PLUGINPACKFILES)GetProcAddress(m_hModule,"PackFiles");
		m_pfnDeleteFiles=(PLUGINDELETEFILES)GetProcAddress(m_hModule,"DeleteFiles");
		m_pfnSetChangeVolProc=(PLUGINSETCHANGEVOLPROC)GetProcAddress(m_hModule,"SetChangeVolProc");
		m_pfnSetProcessDataProc=(PLUGINSETPROCESSDATAPROC)GetProcAddress(m_hModule,"SetProcessDataProc");
		m_pfnConfigurePacker=(PLUGINCONFIGUREPACKER)GetProcAddress(m_hModule,"ConfigurePacker");
		m_pfnGetPackerCaps=(PLUGINGETPACKERCAPS)GetProcAddress(m_hModule,"GetPackerCaps");
		m_pfnCanYouHandleThisFile=(PLUGINCANYOUHANDLETHISFILE)GetProcAddress(m_hModule,"CanYouHandleThisFile");
		m_pfnPackSetDefaultParams=(PLUGINPACKSETDEFAULTPARAMS)GetProcAddress(m_hModule,"PackSetDefaultParams");
	}

	if ( LoadedOK() )
	{
		if (m_pfnPackSetDefaultParams)
		{
			PackDefaultParamStruct dps;

			dps.size = sizeof(dps);
			dps.PluginInterfaceVersionLow = 10;
			dps.PluginInterfaceVersionHi = 2;
			strcpy(dps.DefaultIniName,"");

			m_pfnPackSetDefaultParams(&dps);
		}
	}
}

bool WcxModule::LoadedOK ()
{
	if ( !(m_hModule && m_pfnOpenArchive && m_pfnCloseArchive && m_pfnReadHeader && m_pfnProcessFile) )
		return false;

	return true;
}

WcxModule::~WcxModule ()
{
	FreeLibrary (m_hModule);
}

WcxModules::WcxModules ()
{
	memset (&m_PluginInfo, 0, sizeof (m_PluginInfo));

	char *lpPluginsPath = StrDuplicate (Info.ModuleName, 260);

	CutToSlash (lpPluginsPath);

	strcat (lpPluginsPath, "Formats");

	m_Modules.Create(10);
	m_ExtraPluginInfo.Create(10);

	FSF.FarRecursiveSearch(lpPluginsPath,"*.wcx",(FRSUSERFUNC)LoadWcxModules,FRS_RECUR,this);

	StrFree(lpPluginsPath);

	m_PluginInfo.pFormatInfo = (ArchiveFormatInfo *) realloc (m_PluginInfo.pFormatInfo, sizeof (ArchiveFormatInfo) * m_PluginInfo.nFormats);

	for (int i=0; i<m_ExtraPluginInfo.GetCount (); i++)
	{
		m_PluginInfo.pFormatInfo[i].dwFlags = AFF_SUPPORT_INTERNAL_EXTRACT|AFF_SUPPORT_INTERNAL_TEST;
		m_PluginInfo.pFormatInfo[i].lpName = m_ExtraPluginInfo[i]->Name;
		m_PluginInfo.pFormatInfo[i].lpDefaultExtention = m_ExtraPluginInfo[i]->DefaultExtention;
	}
}

WcxModules::~WcxModules ()
{
	if ( m_PluginInfo.pFormatInfo )
		free (m_PluginInfo.pFormatInfo);

	m_ExtraPluginInfo.Free ();
	m_Modules.Free ();
}

WcxModule *WcxModules::IsArchive (QueryArchiveStruct *pQAS, int *nModuleNum)
{
	WcxModule *TrueArc = NULL;

    *nModuleNum = -1;

	for (int i=0; i<m_Modules.GetCount(); i++)
	{
		if ( m_Modules[i]->m_pfnCanYouHandleThisFile )
		{
			if (m_Modules[i]->m_pfnCanYouHandleThisFile (pQAS->lpFileName))
			{
				TrueArc = m_Modules[i];
				*nModuleNum = i;
				break;
			}
		}
		else
		{
			tOpenArchiveData OpenArchiveData = {0};

			OpenArchiveData.ArcName = (char *)pQAS->lpFileName;
			OpenArchiveData.OpenMode = PK_OM_LIST;

			HANDLE hArchive = m_Modules[i]->m_pfnOpenArchive (&OpenArchiveData);

			if (hArchive)
			{
				m_Modules[i]->m_pfnCloseArchive (hArchive);
				TrueArc = m_Modules[i];
				*nModuleNum = i;
				break;
			}
		}
	}

	return TrueArc;
}

int WINAPI WcxModules::LoadWcxModules (const WIN32_FIND_DATA *pFindData,
		const char *lpFullName,
		WcxModules *pModules
		)
{
	if ( pFindData->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
		return TRUE;

	WcxModule *pModule = new WcxModule (lpFullName);

	if ( !pModule )
		return TRUE;

	if ( !pModule->LoadedOK () )
	{
		delete pModule;
		return TRUE;
	}

    pModules->m_PluginInfo.nFormats++;

    ExtraPluginInfo *pExtraPluginInfo = (ExtraPluginInfo *) malloc (sizeof (ExtraPluginInfo));

	strcpy(pExtraPluginInfo->Name,FSF.PointToName(lpFullName));
	*strrchr(pExtraPluginInfo->Name,'.') = 0;
	strcpy(pExtraPluginInfo->DefaultExtention,pExtraPluginInfo->Name);
	strcat(pExtraPluginInfo->Name," [wcx]");

	pModules->m_ExtraPluginInfo.Add (pExtraPluginInfo);
	pModules->m_Modules.Add (pModule);

	return TRUE;
}

void WcxModules::GetArchivePluginInfo (ArchivePluginInfo *ai)
{
	ai->nFormats = m_PluginInfo.nFormats;
	ai->pFormatInfo = m_PluginInfo.pFormatInfo;
}

bool WcxModules::GetDefaultCommand (int nFormat, int nCommand, char *lpCommand)
{
	return false;
}

WcxArchive::WcxArchive (WcxModule *pModule, int nModuleNum, const char *lpFileName)
{
	m_pModule = pModule;

	m_lpFileName = StrDuplicate (lpFileName);

	m_nModuleNum = nModuleNum;

	m_hArchive = NULL;

	CreateClassThunk (WcxArchive, ProcessDataProc, m_pfnProcessDataProc);
	CreateClassThunk (WcxArchive, SetChangeVolProc, m_pfnSetChangeVolProc);

	m_pfnCallback = NULL;
}

WcxArchive::~WcxArchive ()
{
	StrFree (m_lpFileName);

	free (m_pfnProcessDataProc);
	free (m_pfnSetChangeVolProc);
}

int WcxArchive::ConvertResult (int nResult)
{
	switch (nResult)
	{
		case E_END_ARCHIVE:
			return E_EOF;
		case E_BAD_ARCHIVE:
			return E_BROKEN;
		case E_BAD_DATA:
			return E_UNEXPECTED_EOF;
		case E_EREAD:
			return E_READ_ERROR;
	}

	return E_UNEXPECTED_EOF;
}

bool __stdcall WcxArchive::pOpenArchive (int nOpMode, ARCHIVECALLBACK pfnCallback)
{
	m_pfnCallback = pfnCallback;

	tOpenArchiveData OpenArchiveData = {0};

	OpenArchiveData.ArcName = m_lpFileName;
	OpenArchiveData.OpenMode = (nOpMode == OM_EXTRACT)?PK_OM_EXTRACT:PK_OM_LIST;

	m_hArchive = m_pModule->m_pfnOpenArchive (&OpenArchiveData);

	if ( m_hArchive )
	{
		if (m_pModule->m_pfnSetProcessDataProc)
			m_pModule->m_pfnSetProcessDataProc (m_hArchive, (tProcessDataProc)m_pfnProcessDataProc);

		if (m_pModule->m_pfnSetChangeVolProc)
			m_pModule->m_pfnSetChangeVolProc (m_hArchive, (tChangeVolProc)m_pfnSetChangeVolProc);

		return true;
	}

	return false;
}

void __stdcall WcxArchive::pCloseArchive ()
{
	m_pModule->m_pfnCloseArchive (m_hArchive);
}

int __stdcall WcxArchive::pGetArchiveItem (ArchiveItemInfo *pItem)
{
	//int nResult = 0;

	//__debug ("%d", m_hArchive);

/*	if (!m_hArchive)
	{
		tOpenArchiveData OpenArchiveData = {0};

		OpenArchiveData.ArcName = m_lpFileName;
		OpenArchiveData.OpenMode = PK_OM_LIST;

		m_hArchive = m_pModule->m_pfnOpenArchive (&OpenArchiveData);

		if (m_hArchive)
		{
			if (m_pModule->m_pfnSetProcessDataProc)
				m_pModule->m_pfnSetProcessDataProc (m_hArchive, ProcessDataProc);
			if (m_pModule->m_pfnSetChangeVolProc)
				m_pModule->m_pfnSetChangeVolProc (m_hArchive, SetChangeVolProc);
		}
	}
	else        */
	//{
		//nResult = m_pModule->m_pfnProcessFile (m_hArchive, PK_SKIP, NULL, NULL);
	//}

	//if (m_hArchive)
	{
		//if (!nResult)
		{
			tHeaderData HeaderData;
			memset (&HeaderData, 0, sizeof (HeaderData));
			//strcpy (HeaderData.ArcName, m_lpFileName);

			int nResult = m_pModule->m_pfnReadHeader (m_hArchive, &HeaderData);

			m_pModule->m_pfnProcessFile (m_hArchive, PK_SKIP, NULL, NULL);

			if ( !nResult )
			{
				CharToOem(HeaderData.FileName,pItem->pi.FindData.cFileName);

				pItem->pi.FindData.dwFileAttributes = HeaderData.FileAttr;
				pItem->pi.FindData.nFileSizeLow = HeaderData.UnpSize;

				FILETIME filetime;
				DosDateTimeToFileTime ((WORD)((DWORD)HeaderData.FileTime >> 16), (WORD)HeaderData.FileTime, &filetime);
				LocalFileTimeToFileTime (&filetime, &pItem->pi.FindData.ftLastWriteTime);
				pItem->pi.FindData.ftCreationTime = pItem->pi.FindData.ftLastAccessTime = pItem->pi.FindData.ftLastWriteTime;

				pItem->pi.PackSize = HeaderData.PackSize;
				pItem->pi.CRC32 = HeaderData.FileCRC;

				return E_SUCCESS;
			}

		}

	//	m_pModule->m_pfnCloseArchive (m_hArchive);
	//	m_hArchive = NULL;
	}

	return ConvertResult (nResult);
}

int __stdcall WcxArchive::pGetArchiveType ()
{
	return (m_nModuleNum);
}

bool __stdcall WcxArchive::pExtract (
		PluginPanelItem *pItems,
		int nItemsNumber,
		const char *lpDestPath,
		const char *lpCurrentFolder
		)
{
	int nProcessed = 0;
	int nResult = 0;

	bool bFound;

	char *lpDestName = StrCreate (260);
	char *lpTemp = StrCreate (260);

	/*if (!m_hArchive)
	{
		tOpenArchiveData OpenArchiveData = {0};

		OpenArchiveData.ArcName = m_lpFileName;
		OpenArchiveData.OpenMode = PK_OM_EXTRACT;

		m_hArchive = m_pModule->m_pfnOpenArchive (&OpenArchiveData);

		if (m_hArchive)
		{
			if (m_pModule->m_pfnSetProcessDataProc)
				m_pModule->m_pfnSetProcessDataProc (m_hArchive, m_pfnProcessDataProc);
			if (m_pModule->m_pfnSetChangeVolProc)
				m_pModule->m_pfnSetChangeVolProc (m_hArchive, m_pfnSetChangeVolProc);
		}
	}*/

	while ( /*m_hArchive &&*/ nResult == 0 )
	{
		tHeaderData HeaderData;
		memset (&HeaderData, 0, sizeof (HeaderData));

		nResult = m_pModule->m_pfnReadHeader (m_hArchive, &HeaderData);

		if ( nResult == 0 )
		{
			CharToOem (HeaderData.FileName, lpTemp);

			bFound = false;

			int i = 0;

			for (; i < nItemsNumber; i++)
			{
				if ( !strcmp (pItems[i].FindData.cFileName, lpTemp) )
				{
					OemToChar (lpDestPath, lpDestName);

					FSF.AddEndSlash (lpDestName);

					char *lpName = HeaderData.FileName;

					if ( *lpCurrentFolder /*&& !strncmp (
							lpName,
							lpCurrentFolder,
							strlen (lpCurrentFolder)
							)*/ )
						lpName += strlen (lpCurrentFolder);

					if ( *lpName == '\\' )
						lpName++;

					strcat (lpDestName, lpName);

					if ( m_pfnCallback )
						m_pfnCallback (AM_START_EXTRACT_FILE, (int)&pItems[i], (int)lpDestName);

					int nProcessResult = m_pModule->m_pfnProcessFile (m_hArchive, PK_EXTRACT, NULL, lpDestName);

					if ( !nProcessResult )
						nProcessed++;

					if ( /*m_bAborted ||*/ nProcessResult || (nProcessed == nItemsNumber) )
						goto l_1;

					bFound = true;

					break;
				}
			}

			if ( !bFound )
				m_pModule->m_pfnProcessFile (m_hArchive, PK_SKIP, NULL, NULL);
		}
	}

l_1:

/*	if (m_hArchive)
	{
		m_pModule->m_pfnCloseArchive (m_hArchive);
		m_hArchive = NULL;
	}*/

	//m_bAborted = false;

	StrFree (lpDestName);
	StrFree (lpTemp);

	return nProcessed!=0;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: xmlDatabase.cxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: hr $ $Date: 2004-08-02 15:20:35 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library 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 this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an AS IS basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#ifndef DBA_XMLDATABASE_HXX
#include "xmlDatabase.hxx"
#endif
#ifndef DBA_XMLFILTER_HXX
#include "xmlfilter.hxx"
#endif
#ifndef _XMLOFF_XMLTOKEN_HXX
#include <xmloff/xmltoken.hxx>
#endif
#ifndef _XMLOFF_XMLNMSPE_HXX
#include <xmloff/xmlnmspe.hxx>
#endif
#ifndef DBA_XMLDATASOURCE_HXX
#include "xmlDataSource.hxx"
#endif
#ifndef DBA_XMLDOCUMENTS_HXX
#include "xmlDocuments.hxx"
#endif
#ifndef DBA_XMLENUMS_HXX
#include "xmlEnums.hxx"
#endif
#ifndef _COM_SUN_STAR_SDB_XREPORTDOCUMENTSSUPPLIER_HPP_
#include <com/sun/star/sdb/XReportDocumentsSupplier.hpp>
#endif
#ifndef _COM_SUN_STAR_SDB_XFORMDOCUMENTSSUPPLIER_HPP_
#include <com/sun/star/sdb/XFormDocumentsSupplier.hpp>
#endif
#ifndef _COM_SUN_STAR_SDBCX_XTABLESSUPPLIER_HPP_
#include <com/sun/star/sdbcx/XTablesSupplier.hpp>
#endif
#ifndef _COM_SUN_STAR_SDB_XQUERYDEFINITIONSSUPPLIER_HPP_
#include <com/sun/star/sdb/XQueryDefinitionsSupplier.hpp>
#endif
#ifndef DBACCESS_SHARED_XMLSTRINGS_HRC
#include "xmlstrings.hrc"
#endif

namespace dbaxml
{
    using namespace ::rtl;
    using namespace ::com::sun::star::uno;
    using namespace ::com::sun::star::sdb;
    using namespace ::com::sun::star::sdbcx;
    using namespace ::com::sun::star::xml::sax;

OXMLDatabase::OXMLDatabase( ODBFilter& rImport,
                sal_uInt16 nPrfx, const OUString& rLName,
                const Reference< XAttributeList > & xAttrList ) :
    SvXMLImportContext( rImport, nPrfx, rLName )
{
}
// -----------------------------------------------------------------------------

OXMLDatabase::~OXMLDatabase()
{
}
// -----------------------------------------------------------------------------

SvXMLImportContext* OXMLDatabase::CreateChildContext(
        sal_uInt16 nPrefix,
        const OUString& rLocalName,
        const Reference< XAttributeList > & xAttrList )
{
    SvXMLImportContext *pContext = 0;
    const SvXMLTokenMap&    rTokenMap   = GetOwnImport().GetDatabaseElemTokenMap();

    switch( rTokenMap.Get( nPrefix, rLocalName ) )
    {
        case XML_TOK_DATASOURCE:
            GetOwnImport().GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
            pContext = new OXMLDataSource( GetOwnImport(), nPrefix, rLocalName,xAttrList );
            break;
        case XML_TOK_FORMS:
            {
                GetOwnImport().GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
                Reference<XFormDocumentsSupplier> xSup(GetOwnImport().GetModel(),UNO_QUERY);
                if ( xSup.is() )
                    pContext = new OXMLDocuments( GetOwnImport(), nPrefix, rLocalName,xSup->getFormDocuments(),SERVICE_NAME_FORM_COLLECTION,SERVICE_SDB_DOCUMENTDEFINITION);
            }
            break;
        case XML_TOK_REPORTS:
            {
                GetOwnImport().GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
                Reference<XReportDocumentsSupplier> xSup(GetOwnImport().GetModel(),UNO_QUERY);
                if ( xSup.is() )
                    pContext = new OXMLDocuments( GetOwnImport(), nPrefix, rLocalName,xSup->getReportDocuments(),SERVICE_NAME_REPORT_COLLECTION,SERVICE_SDB_DOCUMENTDEFINITION);
            }
            break;
        case XML_TOK_QUERIES:
            {
                GetOwnImport().GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
                Reference<XQueryDefinitionsSupplier> xSup(GetOwnImport().GetModel(),UNO_QUERY);
                if ( xSup.is() )
                    pContext = new OXMLDocuments( GetOwnImport(), nPrefix, rLocalName,xSup->getQueryDefinitions(),SERVICE_NAME_QUERY_COLLECTION);
            }
            break;
        case XML_TOK_TABLES:
            {
                GetOwnImport().GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
                Reference<XTablesSupplier> xSup(GetOwnImport().GetModel(),UNO_QUERY);
                if ( xSup.is() )
                    pContext = new OXMLDocuments( GetOwnImport(), nPrefix, rLocalName,xSup->getTables());
            }
            break;
    }

    if( !pContext )
        pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName );

    return pContext;
}
// -----------------------------------------------------------------------------
ODBFilter& OXMLDatabase::GetOwnImport()
{
    return static_cast<ODBFilter&>(GetImport());
}

//----------------------------------------------------------------------------
} // namespace dbaxml
// -----------------------------------------------------------------------------
<commit_msg>INTEGRATION: CWS dba24 (1.2.80); FILE MERGED 2005/03/04 13:09:42 oj 1.2.80.2: #i42460# changes for the separation of datasource and database document(model) 2005/02/18 12:44:40 oj 1.2.80.1: #i42460# changes for the separation of datasource and database document(model)<commit_after>/*************************************************************************
 *
 *  $RCSfile: xmlDatabase.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: vg $ $Date: 2005-03-10 16:39:53 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library 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 this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an AS IS basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#ifndef DBA_XMLDATABASE_HXX
#include "xmlDatabase.hxx"
#endif
#ifndef DBA_XMLFILTER_HXX
#include "xmlfilter.hxx"
#endif
#ifndef _XMLOFF_XMLTOKEN_HXX
#include <xmloff/xmltoken.hxx>
#endif
#ifndef _XMLOFF_XMLNMSPE_HXX
#include <xmloff/xmlnmspe.hxx>
#endif
#ifndef DBA_XMLDATASOURCE_HXX
#include "xmlDataSource.hxx"
#endif
#ifndef DBA_XMLDOCUMENTS_HXX
#include "xmlDocuments.hxx"
#endif
#ifndef DBA_XMLENUMS_HXX
#include "xmlEnums.hxx"
#endif
#ifndef _COM_SUN_STAR_SDB_XREPORTDOCUMENTSSUPPLIER_HPP_
#include <com/sun/star/sdb/XReportDocumentsSupplier.hpp>
#endif
#ifndef _COM_SUN_STAR_SDB_XFORMDOCUMENTSSUPPLIER_HPP_
#include <com/sun/star/sdb/XFormDocumentsSupplier.hpp>
#endif
#ifndef _COM_SUN_STAR_SDBCX_XTABLESSUPPLIER_HPP_
#include <com/sun/star/sdbcx/XTablesSupplier.hpp>
#endif
#ifndef _COM_SUN_STAR_SDB_XQUERYDEFINITIONSSUPPLIER_HPP_
#include <com/sun/star/sdb/XQueryDefinitionsSupplier.hpp>
#endif
#ifndef DBACCESS_SHARED_XMLSTRINGS_HRC
#include "xmlstrings.hrc"
#endif

namespace dbaxml
{
    using namespace ::rtl;
    using namespace ::com::sun::star::uno;
    using namespace ::com::sun::star::sdb;
    using namespace ::com::sun::star::sdbcx;
    using namespace ::com::sun::star::xml::sax;

OXMLDatabase::OXMLDatabase( ODBFilter& rImport,
                sal_uInt16 nPrfx, const OUString& rLName,
                const Reference< XAttributeList > & xAttrList ) :
    SvXMLImportContext( rImport, nPrfx, rLName )
{
}
// -----------------------------------------------------------------------------

OXMLDatabase::~OXMLDatabase()
{
}
// -----------------------------------------------------------------------------

SvXMLImportContext* OXMLDatabase::CreateChildContext(
        sal_uInt16 nPrefix,
        const OUString& rLocalName,
        const Reference< XAttributeList > & xAttrList )
{
    SvXMLImportContext *pContext = 0;
    const SvXMLTokenMap&    rTokenMap   = GetOwnImport().GetDatabaseElemTokenMap();

    switch( rTokenMap.Get( nPrefix, rLocalName ) )
    {
        case XML_TOK_DATASOURCE:
            GetOwnImport().GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
            pContext = new OXMLDataSource( GetOwnImport(), nPrefix, rLocalName,xAttrList );
            break;
        case XML_TOK_FORMS:
            {
                GetOwnImport().GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
                Reference<XFormDocumentsSupplier> xSup(GetOwnImport().GetModel(),UNO_QUERY);
                if ( xSup.is() )
                    pContext = new OXMLDocuments( GetOwnImport(), nPrefix, rLocalName,xSup->getFormDocuments(),SERVICE_NAME_FORM_COLLECTION,SERVICE_SDB_DOCUMENTDEFINITION);
            }
            break;
        case XML_TOK_REPORTS:
            {
                GetOwnImport().GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
                Reference<XReportDocumentsSupplier> xSup(GetOwnImport().GetModel(),UNO_QUERY);
                if ( xSup.is() )
                    pContext = new OXMLDocuments( GetOwnImport(), nPrefix, rLocalName,xSup->getReportDocuments(),SERVICE_NAME_REPORT_COLLECTION,SERVICE_SDB_DOCUMENTDEFINITION);
            }
            break;
        case XML_TOK_QUERIES:
            {
                GetOwnImport().GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
                Reference<XQueryDefinitionsSupplier> xSup(GetOwnImport().getDataSource(),UNO_QUERY);
                if ( xSup.is() )
                    pContext = new OXMLDocuments( GetOwnImport(), nPrefix, rLocalName,xSup->getQueryDefinitions(),SERVICE_NAME_QUERY_COLLECTION);
            }
            break;
        case XML_TOK_TABLES:
            {
                GetOwnImport().GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
                Reference<XTablesSupplier> xSup(GetOwnImport().getDataSource(),UNO_QUERY);
                if ( xSup.is() )
                    pContext = new OXMLDocuments( GetOwnImport(), nPrefix, rLocalName,xSup->getTables());
            }
            break;
    }

    if( !pContext )
        pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName );

    return pContext;
}
// -----------------------------------------------------------------------------
ODBFilter& OXMLDatabase::GetOwnImport()
{
    return static_cast<ODBFilter&>(GetImport());
}

//----------------------------------------------------------------------------
} // namespace dbaxml
// -----------------------------------------------------------------------------
<|endoftext|>