<commit_before>/*
 * Copyright (C) 2015 ScyllaDB
 *
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla 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 General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once

#include "database_fwd.hh"
#include "shared_sstable.hh"
#include "gc_clock.hh"
#include "compaction_weight_registration.hh"
#include "utils/UUID.hh"
#include <seastar/core/thread.hh>
#include <functional>

class flat_mutation_reader;

namespace sstables {

    enum class compaction_type;

    class compaction_options {
    public:
        struct regular {
        };
        struct cleanup {
        };
        struct upgrade {
        };
        struct scrub {
            bool skip_corrupted;
        };

    private:
        using options_variant = std::variant<regular, cleanup, upgrade, scrub>;

    private:
        options_variant _options;

    private:
        explicit compaction_options(options_variant options) : _options(std::move(options)) {
        }

    public:
        static compaction_options make_regular() {
            return compaction_options(regular{});
        }

        static compaction_options make_cleanup() {
            return compaction_options(cleanup{});
        }

        static compaction_options make_upgrade() {
            return compaction_options(upgrade{});
        }

        static compaction_options make_scrub(bool skip_corrupted) {
            return compaction_options(scrub{skip_corrupted});
        }

        template <typename... Visitor>
        auto visit(Visitor&&... visitor) const {
            return std::visit(std::forward<Visitor>(visitor)..., _options);
        }

        compaction_type type() const;
    };

    struct compaction_descriptor {
        // List of sstables to be compacted.
        std::vector<sstables::shared_sstable> sstables;
        // Level of sstable(s) created by compaction procedure.
        int level;
        // Threshold size for sstable(s) to be created.
        uint64_t max_sstable_bytes;
        // Run identifier of output sstables.
        utils::UUID run_identifier;
        // Holds ownership of a weight assigned to this compaction iff it's a regular one.
        std::optional<compaction_weight_registration> weight_registration;
        // Calls compaction manager's task for this compaction to release reference to exhausted sstables.
        std::function<void(const std::vector<shared_sstable>& exhausted_sstables)> release_exhausted;
        // The options passed down to the compaction code.
        // This also selects the kind of compaction to do.
        compaction_options options = compaction_options::make_regular();

        compaction_descriptor() = default;

        static constexpr int default_level = 0;
        static constexpr uint64_t default_max_sstable_bytes = std::numeric_limits<uint64_t>::max();

        explicit compaction_descriptor(std::vector<sstables::shared_sstable> sstables, int level = default_level,
                                       uint64_t max_sstable_bytes = default_max_sstable_bytes,
                                       utils::UUID run_identifier = utils::make_random_uuid(),
                                       compaction_options options = compaction_options::make_regular())
            : sstables(std::move(sstables))
            , level(level)
            , max_sstable_bytes(max_sstable_bytes)
            , run_identifier(run_identifier)
            , options(options)
        {}
    };

    struct resharding_descriptor {
        std::vector<sstables::shared_sstable> sstables;
        uint64_t max_sstable_bytes;
        shard_id reshard_at;
        uint32_t level;
    };

    enum class compaction_type {
        Compaction = 0,
        Cleanup = 1,
        Validation = 2,
        Scrub = 3,
        Index_build = 4,
        Reshard = 5,
        Upgrade = 6,
    };

    static inline sstring compaction_name(compaction_type type) {
        switch (type) {
        case compaction_type::Compaction:
            return "COMPACTION";
        case compaction_type::Cleanup:
            return "CLEANUP";
        case compaction_type::Validation:
            return "VALIDATION";
        case compaction_type::Scrub:
            return "SCRUB";
        case compaction_type::Index_build:
            return "INDEX_BUILD";
        case compaction_type::Reshard:
            return "RESHARD";
        case compaction_type::Upgrade:
            return "UPGRADE";
        default:
            throw std::runtime_error("Invalid Compaction Type");
        }
    }

    struct compaction_info {
        compaction_type type = compaction_type::Compaction;
        table* cf = nullptr;
        sstring ks_name;
        sstring cf_name;
        size_t sstables = 0;
        uint64_t start_size = 0;
        uint64_t end_size = 0;
        uint64_t total_partitions = 0;
        uint64_t total_keys_written = 0;
        int64_t ended_at;
        std::vector<shared_sstable> new_sstables;
        sstring stop_requested;
        bool tracking = true;
        utils::UUID run_identifier;
        struct replacement {
            const std::vector<shared_sstable> removed;
            const std::vector<shared_sstable> added;
        };
        std::vector<replacement> pending_replacements;

        bool is_stop_requested() const {
            return stop_requested.size() > 0;
        }

        void stop(sstring reason) {
            stop_requested = std::move(reason);
        }

        void stop_tracking() {
            tracking = false;
        }
    };

    struct compaction_completion_desc {
        std::vector<shared_sstable> input_sstables;
        std::vector<shared_sstable> output_sstables;
    };

    // Replaces old sstable(s) by new one(s) which contain all non-expired data.
    using replacer_fn = std::function<void(compaction_completion_desc)>;

    // Compact a list of N sstables into M sstables.
    // Returns info about the finished compaction, which includes vector to new sstables.
    //
    // creator is used to get a sstable object for a new sstable that will be written.
    // replacer will replace old sstables by new ones in the column family.
    // max_sstable_size is a relaxed limit size for a sstable to be generated.
    // Example: It's okay for the size of a new sstable to go beyond max_sstable_size
    // when writing its last partition.
    // sstable_level will be level of the sstable(s) to be created by this function.
    // If descriptor.cleanup is true, mutation that doesn't belong to current node will be
    // cleaned up, log messages will inform the user that compact_sstables runs for
    // cleaning operation, and compaction history will not be updated.
    future<compaction_info> compact_sstables(sstables::compaction_descriptor descriptor, column_family& cf,
        std::function<shared_sstable()> creator, replacer_fn replacer);

    // Compacts a set of N shared sstables into M sstables. For every shard involved,
    // i.e. which owns any of the sstables, a new unshared sstable is created.
    future<std::vector<shared_sstable>> reshard_sstables(std::vector<shared_sstable> sstables,
            column_family& cf, std::function<shared_sstable(shard_id)> creator,
        uint64_t max_sstable_size, uint32_t sstable_level);

    // Return list of expired sstables for column family cf.
    // A sstable is fully expired *iff* its max_local_deletion_time precedes gc_before and its
    // max timestamp is lower than any other relevant sstable.
    // In simpler words, a sstable is fully expired if all of its live cells with TTL is expired
    // and possibly doesn't contain any tombstone that covers cells in other sstables.
    std::unordered_set<sstables::shared_sstable>
    get_fully_expired_sstables(column_family& cf, const std::vector<sstables::shared_sstable>& compacting, gc_clock::time_point gc_before);

    // For tests, can drop after we virtualize sstables.
    flat_mutation_reader make_scrubbing_reader(flat_mutation_reader rd, bool skip_corrupted);
}
<commit_msg>compaction: Add ranges for cache invalidation to compaction_completion_desc<commit_after>/*
 * Copyright (C) 2015 ScyllaDB
 *
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla 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 General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once

#include "database_fwd.hh"
#include "shared_sstable.hh"
#include "gc_clock.hh"
#include "compaction_weight_registration.hh"
#include "utils/UUID.hh"
#include "dht/i_partitioner.hh"
#include <seastar/core/thread.hh>
#include <functional>

class flat_mutation_reader;

namespace sstables {

    enum class compaction_type;

    class compaction_options {
    public:
        struct regular {
        };
        struct cleanup {
        };
        struct upgrade {
        };
        struct scrub {
            bool skip_corrupted;
        };

    private:
        using options_variant = std::variant<regular, cleanup, upgrade, scrub>;

    private:
        options_variant _options;

    private:
        explicit compaction_options(options_variant options) : _options(std::move(options)) {
        }

    public:
        static compaction_options make_regular() {
            return compaction_options(regular{});
        }

        static compaction_options make_cleanup() {
            return compaction_options(cleanup{});
        }

        static compaction_options make_upgrade() {
            return compaction_options(upgrade{});
        }

        static compaction_options make_scrub(bool skip_corrupted) {
            return compaction_options(scrub{skip_corrupted});
        }

        template <typename... Visitor>
        auto visit(Visitor&&... visitor) const {
            return std::visit(std::forward<Visitor>(visitor)..., _options);
        }

        compaction_type type() const;
    };

    struct compaction_descriptor {
        // List of sstables to be compacted.
        std::vector<sstables::shared_sstable> sstables;
        // Level of sstable(s) created by compaction procedure.
        int level;
        // Threshold size for sstable(s) to be created.
        uint64_t max_sstable_bytes;
        // Run identifier of output sstables.
        utils::UUID run_identifier;
        // Holds ownership of a weight assigned to this compaction iff it's a regular one.
        std::optional<compaction_weight_registration> weight_registration;
        // Calls compaction manager's task for this compaction to release reference to exhausted sstables.
        std::function<void(const std::vector<shared_sstable>& exhausted_sstables)> release_exhausted;
        // The options passed down to the compaction code.
        // This also selects the kind of compaction to do.
        compaction_options options = compaction_options::make_regular();

        compaction_descriptor() = default;

        static constexpr int default_level = 0;
        static constexpr uint64_t default_max_sstable_bytes = std::numeric_limits<uint64_t>::max();

        explicit compaction_descriptor(std::vector<sstables::shared_sstable> sstables, int level = default_level,
                                       uint64_t max_sstable_bytes = default_max_sstable_bytes,
                                       utils::UUID run_identifier = utils::make_random_uuid(),
                                       compaction_options options = compaction_options::make_regular())
            : sstables(std::move(sstables))
            , level(level)
            , max_sstable_bytes(max_sstable_bytes)
            , run_identifier(run_identifier)
            , options(options)
        {}
    };

    struct resharding_descriptor {
        std::vector<sstables::shared_sstable> sstables;
        uint64_t max_sstable_bytes;
        shard_id reshard_at;
        uint32_t level;
    };

    enum class compaction_type {
        Compaction = 0,
        Cleanup = 1,
        Validation = 2,
        Scrub = 3,
        Index_build = 4,
        Reshard = 5,
        Upgrade = 6,
    };

    static inline sstring compaction_name(compaction_type type) {
        switch (type) {
        case compaction_type::Compaction:
            return "COMPACTION";
        case compaction_type::Cleanup:
            return "CLEANUP";
        case compaction_type::Validation:
            return "VALIDATION";
        case compaction_type::Scrub:
            return "SCRUB";
        case compaction_type::Index_build:
            return "INDEX_BUILD";
        case compaction_type::Reshard:
            return "RESHARD";
        case compaction_type::Upgrade:
            return "UPGRADE";
        default:
            throw std::runtime_error("Invalid Compaction Type");
        }
    }

    struct compaction_info {
        compaction_type type = compaction_type::Compaction;
        table* cf = nullptr;
        sstring ks_name;
        sstring cf_name;
        size_t sstables = 0;
        uint64_t start_size = 0;
        uint64_t end_size = 0;
        uint64_t total_partitions = 0;
        uint64_t total_keys_written = 0;
        int64_t ended_at;
        std::vector<shared_sstable> new_sstables;
        sstring stop_requested;
        bool tracking = true;
        utils::UUID run_identifier;
        struct replacement {
            const std::vector<shared_sstable> removed;
            const std::vector<shared_sstable> added;
        };
        std::vector<replacement> pending_replacements;

        bool is_stop_requested() const {
            return stop_requested.size() > 0;
        }

        void stop(sstring reason) {
            stop_requested = std::move(reason);
        }

        void stop_tracking() {
            tracking = false;
        }
    };

    struct compaction_completion_desc {
        std::vector<shared_sstable> input_sstables;
        std::vector<shared_sstable> output_sstables;
        // Set of compacted partition ranges that should be invalidated in the cache.
        dht::partition_range_vector ranges_for_cache_invalidation;
    };

    // Replaces old sstable(s) by new one(s) which contain all non-expired data.
    using replacer_fn = std::function<void(compaction_completion_desc)>;

    // Compact a list of N sstables into M sstables.
    // Returns info about the finished compaction, which includes vector to new sstables.
    //
    // creator is used to get a sstable object for a new sstable that will be written.
    // replacer will replace old sstables by new ones in the column family.
    // max_sstable_size is a relaxed limit size for a sstable to be generated.
    // Example: It's okay for the size of a new sstable to go beyond max_sstable_size
    // when writing its last partition.
    // sstable_level will be level of the sstable(s) to be created by this function.
    // If descriptor.cleanup is true, mutation that doesn't belong to current node will be
    // cleaned up, log messages will inform the user that compact_sstables runs for
    // cleaning operation, and compaction history will not be updated.
    future<compaction_info> compact_sstables(sstables::compaction_descriptor descriptor, column_family& cf,
        std::function<shared_sstable()> creator, replacer_fn replacer);

    // Compacts a set of N shared sstables into M sstables. For every shard involved,
    // i.e. which owns any of the sstables, a new unshared sstable is created.
    future<std::vector<shared_sstable>> reshard_sstables(std::vector<shared_sstable> sstables,
            column_family& cf, std::function<shared_sstable(shard_id)> creator,
        uint64_t max_sstable_size, uint32_t sstable_level);

    // Return list of expired sstables for column family cf.
    // A sstable is fully expired *iff* its max_local_deletion_time precedes gc_before and its
    // max timestamp is lower than any other relevant sstable.
    // In simpler words, a sstable is fully expired if all of its live cells with TTL is expired
    // and possibly doesn't contain any tombstone that covers cells in other sstables.
    std::unordered_set<sstables::shared_sstable>
    get_fully_expired_sstables(column_family& cf, const std::vector<sstables::shared_sstable>& compacting, gc_clock::time_point gc_before);

    // For tests, can drop after we virtualize sstables.
    flat_mutation_reader make_scrubbing_reader(flat_mutation_reader rd, bool skip_corrupted);
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: hints.hxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: obo $ $Date: 2004-11-16 15:37:22 $
 *
 *  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 _HINTS_HXX
#define _HINTS_HXX

#ifndef _TABLE_HXX //autogen
#include <tools/table.hxx>
#endif
#ifndef _SWATRSET_HXX
#include <swatrset.hxx>
#endif

class SwFmt;
class OutputDevice;
class SwTable;
class SwNode;
class SwNodes;
class SwCntntNode;
class SwPageFrm;
class SwFrm;
class SwTxtNode;
class SwHistory;

// Basis-Klasse fuer alle Message-Hints:
//  "Overhead" vom SfxPoolItem wird hier behandelt
class SwMsgPoolItem : public SfxPoolItem
{
public:
    SwMsgPoolItem( USHORT nWhich );

    // "Overhead" vom SfxPoolItem
    virtual int             operator==( const SfxPoolItem& ) const;
    virtual SfxPoolItem*    Clone( SfxItemPool* pPool = 0 ) const;
};

// ---------------------------------------
// SwPtrMsgPoolItem (altes SwObjectDying!)
// ---------------------------------------

class SwPtrMsgPoolItem : public SwMsgPoolItem
{
public:
    void * pObject;

    SwPtrMsgPoolItem( USHORT nId, void * pObj )
        : SwMsgPoolItem( nId ), pObject( pObj )
    {}
};

/*
 * SwFmtChg wird verschickt, wenn ein Format gegen ein anderes
 * Format ausgewechselt worden ist. Es werden immer 2. Hints verschickt,
 * das alte und neue Format.
 */
class SwFmtChg: public SwMsgPoolItem
{
public:
    SwFmt *pChangedFmt;
    SwFmtChg( SwFmt *pFmt );
};

class SwInsChr: public SwMsgPoolItem
{
public:
    xub_StrLen nPos;

    SwInsChr( USHORT nP );
};

class SwInsTxt: public SwMsgPoolItem
{
public:
    xub_StrLen nPos;
    xub_StrLen nLen;

    SwInsTxt( xub_StrLen nP, xub_StrLen nL );
};

class SwDelChr: public SwMsgPoolItem
{
public:
    xub_StrLen nPos;

    SwDelChr( xub_StrLen nP );
};

class SwDelTxt: public SwMsgPoolItem
{
public:
    xub_StrLen nStart;
    xub_StrLen nLen;

    SwDelTxt( xub_StrLen nS, xub_StrLen nL );
};

class SwUpdateAttr: public SwMsgPoolItem
{
public:
    xub_StrLen nStart;
    xub_StrLen nEnd;
    USHORT nWhichAttr;
    SwUpdateAttr( xub_StrLen nS, xub_StrLen nE, USHORT nW );
};

// SwRefMarkFldUpdate wird verschickt, wenn sich die ReferenzMarkierungen
// Updaten sollen. Um Seiten-/KapitelNummer feststellen zu koennen, muss
// der akt. Frame befragt werden. Dafuer wird das akt. OutputDevice benoetigt.
class SwRefMarkFldUpdate : public SwMsgPoolItem
{
public:
    const OutputDevice* pOut;       // Pointer auf das aktuelle Output-Device
    SwRefMarkFldUpdate( const OutputDevice* );
};

// SwDocPosUpdate wird verschickt, um zu signalisieren, dass nur die
// Frames ab oder bis zu einer bestimmten dokument-globalen Position
// geupdated werden brauchen. Zur Zeit wird dies nur beim Updaten
// von Seitennummernfeldern benoetigt.

class SwDocPosUpdate : public SwMsgPoolItem
{
public:
    const long nDocPos;
    SwDocPosUpdate( const long nDocPos );
};

// SwTableFmlUpdate wird verschickt, wenn sich die Tabelle neu berechnen soll
// JP 16.02.99: oder wenn die Tabelle selbst gemergt oder gesplittet wird
enum TableFmlUpdtFlags { TBL_CALC = 0,
                         TBL_BOXNAME,
                         TBL_BOXPTR,
                         TBL_RELBOXNAME,
                         TBL_MERGETBL,
                         TBL_SPLITTBL
                       };
class SwTableFmlUpdate : public SwMsgPoolItem
{
public:
    const SwTable* pTbl;        // Pointer auf die zu aktuelle Tabelle
    union {
        const SwTable* pDelTbl;     // Merge: Ptr auf die zu loeschende Tabelle
        const String* pNewTblNm;    // Split: der Name der neuen Tabelle
    } DATA;
    SwHistory* pHistory;
    USHORT nSplitLine;          // Split: ab dieser BaseLine wird gespl.
    TableFmlUpdtFlags eFlags;
    BOOL bModified : 1;
    BOOL bBehindSplitLine : 1;

    SwTableFmlUpdate( const SwTable* );
};

class SwAutoFmtGetDocNode: public SwMsgPoolItem
{
public:
    const SwCntntNode* pCntntNode;
    const SwNodes* pNodes;

    SwAutoFmtGetDocNode( const SwNodes* pNds );
};

/*
 * SwAttrSetChg wird verschicht, wenn sich in dem SwAttrSet rTheChgdSet
 * etwas veraendert hat. Es werden immer 2. Hints
 * verschickt, die alten und neuen Items in dem rTheChgdSet.
 */
class SwAttrSetChg: public SwMsgPoolItem
{
    BOOL bDelSet;
    SwAttrSet* pChgSet;             // was sich veraendert hat
    const SwAttrSet* pTheChgdSet;   // wird nur zum Vergleichen gebraucht !!
public:
    SwAttrSetChg( const SwAttrSet& rTheSet, SwAttrSet& rSet );
    SwAttrSetChg( const SwAttrSetChg& );
    ~SwAttrSetChg();

    // was sich veraendert hat
    const SwAttrSet* GetChgSet() const  { return pChgSet; }
          SwAttrSet* GetChgSet()        { return pChgSet; }

    // wo es sich geaendert hat
    const SwAttrSet* GetTheChgdSet() const  { return pTheChgdSet; }

    SfxItemState GetItemState( USHORT nWhich, BOOL bSrchInParent = TRUE,
                               const SfxPoolItem **ppItem = 0 ) const
    {   return pChgSet->GetItemState( nWhich, bSrchInParent, ppItem ); }

    USHORT Count() const { return pChgSet->Count(); }
    void ClearItem( USHORT nWhich = 0 )
#ifdef PRODUCT
    { pChgSet->ClearItem( nWhich ); }
#else
        ;
#endif
};

class SwCondCollCondChg: public SwMsgPoolItem
{
public:
    SwFmt *pChangedFmt;
    SwCondCollCondChg( SwFmt *pFmt );
};

class SwVirtPageNumInfo: public SwMsgPoolItem
{
    const SwPageFrm *pPage;
    const SwPageFrm *pOrigPage;
    const SwFrm     *pFrm;      //An einem Absatz/Tabelle koennen mehrere
                                //Attribute sitzen. Der Frame muss dann
                                //muss dann letztlich bei bestimmen
                                //welches Attribut gilt und um welche physikalische
                                //Seite es sich handelt.
public:
    SwVirtPageNumInfo( const SwPageFrm *pPg );

    const SwPageFrm *GetPage()          { return pPage;    }
    const SwPageFrm *GetOrigPage()      { return pOrigPage;}
    const SwFrm *GetFrm()               { return pFrm; }
    void  SetInfo( const SwPageFrm *pPg,
                   const SwFrm *pF  )   { pFrm = pF, pPage = pPg; }
};

DECLARE_TABLE( SwTxtNodeTable, SwTxtNode* )

class SwNumRuleInfo : public SwMsgPoolItem
{
    SwTxtNodeTable aList;
    const String& rName;
public:
    SwNumRuleInfo( const String& rRuleName );

    const String& GetName() const { return rName; }
    void AddNode( SwTxtNode& rNd );

    // erzeuge die Liste aller Nodes der NumRule in dem angegebenem Doc
    // Der Code steht im docnum.cxx
    // #111955#
    void MakeList( SwDoc& rDoc, BOOL bOutline = FALSE );

    const SwTxtNodeTable& GetList() const { return aList; }
};

class SwNRuleLowerLevel : public SwMsgPoolItem
{
    const String& rName;
    BYTE nLvl;
public:
    SwNRuleLowerLevel( const String& rRuleName, BYTE nLevel );

    const String& GetName() const { return rName; }
    BYTE GetLevel() const { return nLvl; }
};

class SwFindNearestNode : public SwMsgPoolItem
{
    const SwNode *pNd, *pFnd;
public:
    SwFindNearestNode( const SwNode& rNd );
    void CheckNode( const SwNode& rNd );

    const SwNode* GetFoundNode() const      { return pFnd; }
};

class SwStringMsgPoolItem : public SwMsgPoolItem
{
    String sStr;
public:

    const String& GetString() const { return sStr; }

    SwStringMsgPoolItem( USHORT nId, const String& rStr )
        : SwMsgPoolItem( nId ), sStr( rStr )
    {}
};

#endif
<commit_msg>INTEGRATION: CWS ooo19126 (1.5.460); FILE MERGED 2005/09/05 13:36:13 rt 1.5.460.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: hints.hxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 01:57:34 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 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
 *
 ************************************************************************/
#ifndef _HINTS_HXX
#define _HINTS_HXX

#ifndef _TABLE_HXX //autogen
#include <tools/table.hxx>
#endif
#ifndef _SWATRSET_HXX
#include <swatrset.hxx>
#endif

class SwFmt;
class OutputDevice;
class SwTable;
class SwNode;
class SwNodes;
class SwCntntNode;
class SwPageFrm;
class SwFrm;
class SwTxtNode;
class SwHistory;

// Basis-Klasse fuer alle Message-Hints:
//  "Overhead" vom SfxPoolItem wird hier behandelt
class SwMsgPoolItem : public SfxPoolItem
{
public:
    SwMsgPoolItem( USHORT nWhich );

    // "Overhead" vom SfxPoolItem
    virtual int             operator==( const SfxPoolItem& ) const;
    virtual SfxPoolItem*    Clone( SfxItemPool* pPool = 0 ) const;
};

// ---------------------------------------
// SwPtrMsgPoolItem (altes SwObjectDying!)
// ---------------------------------------

class SwPtrMsgPoolItem : public SwMsgPoolItem
{
public:
    void * pObject;

    SwPtrMsgPoolItem( USHORT nId, void * pObj )
        : SwMsgPoolItem( nId ), pObject( pObj )
    {}
};

/*
 * SwFmtChg wird verschickt, wenn ein Format gegen ein anderes
 * Format ausgewechselt worden ist. Es werden immer 2. Hints verschickt,
 * das alte und neue Format.
 */
class SwFmtChg: public SwMsgPoolItem
{
public:
    SwFmt *pChangedFmt;
    SwFmtChg( SwFmt *pFmt );
};

class SwInsChr: public SwMsgPoolItem
{
public:
    xub_StrLen nPos;

    SwInsChr( USHORT nP );
};

class SwInsTxt: public SwMsgPoolItem
{
public:
    xub_StrLen nPos;
    xub_StrLen nLen;

    SwInsTxt( xub_StrLen nP, xub_StrLen nL );
};

class SwDelChr: public SwMsgPoolItem
{
public:
    xub_StrLen nPos;

    SwDelChr( xub_StrLen nP );
};

class SwDelTxt: public SwMsgPoolItem
{
public:
    xub_StrLen nStart;
    xub_StrLen nLen;

    SwDelTxt( xub_StrLen nS, xub_StrLen nL );
};

class SwUpdateAttr: public SwMsgPoolItem
{
public:
    xub_StrLen nStart;
    xub_StrLen nEnd;
    USHORT nWhichAttr;
    SwUpdateAttr( xub_StrLen nS, xub_StrLen nE, USHORT nW );
};

// SwRefMarkFldUpdate wird verschickt, wenn sich die ReferenzMarkierungen
// Updaten sollen. Um Seiten-/KapitelNummer feststellen zu koennen, muss
// der akt. Frame befragt werden. Dafuer wird das akt. OutputDevice benoetigt.
class SwRefMarkFldUpdate : public SwMsgPoolItem
{
public:
    const OutputDevice* pOut;       // Pointer auf das aktuelle Output-Device
    SwRefMarkFldUpdate( const OutputDevice* );
};

// SwDocPosUpdate wird verschickt, um zu signalisieren, dass nur die
// Frames ab oder bis zu einer bestimmten dokument-globalen Position
// geupdated werden brauchen. Zur Zeit wird dies nur beim Updaten
// von Seitennummernfeldern benoetigt.

class SwDocPosUpdate : public SwMsgPoolItem
{
public:
    const long nDocPos;
    SwDocPosUpdate( const long nDocPos );
};

// SwTableFmlUpdate wird verschickt, wenn sich die Tabelle neu berechnen soll
// JP 16.02.99: oder wenn die Tabelle selbst gemergt oder gesplittet wird
enum TableFmlUpdtFlags { TBL_CALC = 0,
                         TBL_BOXNAME,
                         TBL_BOXPTR,
                         TBL_RELBOXNAME,
                         TBL_MERGETBL,
                         TBL_SPLITTBL
                       };
class SwTableFmlUpdate : public SwMsgPoolItem
{
public:
    const SwTable* pTbl;        // Pointer auf die zu aktuelle Tabelle
    union {
        const SwTable* pDelTbl;     // Merge: Ptr auf die zu loeschende Tabelle
        const String* pNewTblNm;    // Split: der Name der neuen Tabelle
    } DATA;
    SwHistory* pHistory;
    USHORT nSplitLine;          // Split: ab dieser BaseLine wird gespl.
    TableFmlUpdtFlags eFlags;
    BOOL bModified : 1;
    BOOL bBehindSplitLine : 1;

    SwTableFmlUpdate( const SwTable* );
};

class SwAutoFmtGetDocNode: public SwMsgPoolItem
{
public:
    const SwCntntNode* pCntntNode;
    const SwNodes* pNodes;

    SwAutoFmtGetDocNode( const SwNodes* pNds );
};

/*
 * SwAttrSetChg wird verschicht, wenn sich in dem SwAttrSet rTheChgdSet
 * etwas veraendert hat. Es werden immer 2. Hints
 * verschickt, die alten und neuen Items in dem rTheChgdSet.
 */
class SwAttrSetChg: public SwMsgPoolItem
{
    BOOL bDelSet;
    SwAttrSet* pChgSet;             // was sich veraendert hat
    const SwAttrSet* pTheChgdSet;   // wird nur zum Vergleichen gebraucht !!
public:
    SwAttrSetChg( const SwAttrSet& rTheSet, SwAttrSet& rSet );
    SwAttrSetChg( const SwAttrSetChg& );
    ~SwAttrSetChg();

    // was sich veraendert hat
    const SwAttrSet* GetChgSet() const  { return pChgSet; }
          SwAttrSet* GetChgSet()        { return pChgSet; }

    // wo es sich geaendert hat
    const SwAttrSet* GetTheChgdSet() const  { return pTheChgdSet; }

    SfxItemState GetItemState( USHORT nWhich, BOOL bSrchInParent = TRUE,
                               const SfxPoolItem **ppItem = 0 ) const
    {   return pChgSet->GetItemState( nWhich, bSrchInParent, ppItem ); }

    USHORT Count() const { return pChgSet->Count(); }
    void ClearItem( USHORT nWhich = 0 )
#ifdef PRODUCT
    { pChgSet->ClearItem( nWhich ); }
#else
        ;
#endif
};

class SwCondCollCondChg: public SwMsgPoolItem
{
public:
    SwFmt *pChangedFmt;
    SwCondCollCondChg( SwFmt *pFmt );
};

class SwVirtPageNumInfo: public SwMsgPoolItem
{
    const SwPageFrm *pPage;
    const SwPageFrm *pOrigPage;
    const SwFrm     *pFrm;      //An einem Absatz/Tabelle koennen mehrere
                                //Attribute sitzen. Der Frame muss dann
                                //muss dann letztlich bei bestimmen
                                //welches Attribut gilt und um welche physikalische
                                //Seite es sich handelt.
public:
    SwVirtPageNumInfo( const SwPageFrm *pPg );

    const SwPageFrm *GetPage()          { return pPage;    }
    const SwPageFrm *GetOrigPage()      { return pOrigPage;}
    const SwFrm *GetFrm()               { return pFrm; }
    void  SetInfo( const SwPageFrm *pPg,
                   const SwFrm *pF  )   { pFrm = pF, pPage = pPg; }
};

DECLARE_TABLE( SwTxtNodeTable, SwTxtNode* )

class SwNumRuleInfo : public SwMsgPoolItem
{
    SwTxtNodeTable aList;
    const String& rName;
public:
    SwNumRuleInfo( const String& rRuleName );

    const String& GetName() const { return rName; }
    void AddNode( SwTxtNode& rNd );

    // erzeuge die Liste aller Nodes der NumRule in dem angegebenem Doc
    // Der Code steht im docnum.cxx
    // #111955#
    void MakeList( SwDoc& rDoc, BOOL bOutline = FALSE );

    const SwTxtNodeTable& GetList() const { return aList; }
};

class SwNRuleLowerLevel : public SwMsgPoolItem
{
    const String& rName;
    BYTE nLvl;
public:
    SwNRuleLowerLevel( const String& rRuleName, BYTE nLevel );

    const String& GetName() const { return rName; }
    BYTE GetLevel() const { return nLvl; }
};

class SwFindNearestNode : public SwMsgPoolItem
{
    const SwNode *pNd, *pFnd;
public:
    SwFindNearestNode( const SwNode& rNd );
    void CheckNode( const SwNode& rNd );

    const SwNode* GetFoundNode() const      { return pFnd; }
};

class SwStringMsgPoolItem : public SwMsgPoolItem
{
    String sStr;
public:

    const String& GetString() const { return sStr; }

    SwStringMsgPoolItem( USHORT nId, const String& rStr )
        : SwMsgPoolItem( nId ), sStr( rStr )
    {}
};

#endif
<|endoftext|>


<commit_before>#ifndef ___INANITY_SCRIPT_STATE_HPP___
#define ___INANITY_SCRIPT_STATE_HPP___

#include "script.hpp"
#include "../meta/Class.hpp"

BEGIN_INANITY

class File;

END_INANITY

BEGIN_INANITY_SCRIPT

class Function;

/// Abstract class incapsulating the state of scripting engine.
/** Script entities (functions, objects, etc) can't be directly
exchanged between instances of State class. */
class State : public Object
{
public:
	/// Registers an information about class.
	virtual void Register(Meta::ClassBase* classMeta) = 0;

	/// Helper method for registering class by type.
	template <typename ClassType>
	void Register()
	{
		Register(ClassType::GetMeta());
	}

	/// Loads a script from file.
	virtual ptr<Function> LoadScript(ptr<File> file) = 0;
};

END_INANITY_SCRIPT

#endif
<commit_msg>added ReclaimInstance method to abstract Script::State class<commit_after>#ifndef ___INANITY_SCRIPT_STATE_HPP___
#define ___INANITY_SCRIPT_STATE_HPP___

#include "script.hpp"
#include "../meta/Class.hpp"

BEGIN_INANITY

class File;

END_INANITY

BEGIN_INANITY_SCRIPT

class Function;

/// Abstract class incapsulating the state of scripting engine.
/** Script entities (functions, objects, etc) can't be directly
exchanged between instances of State class. */
class State : public Object
{
public:
	/// Registers an information about class.
	virtual void Register(Meta::ClassBase* classMeta) = 0;

	/// Helper method for registering class by type.
	template <typename ClassType>
	void Register()
	{
		Register(ClassType::GetMeta());
	}

	/// Loads a script from file.
	virtual ptr<Function> LoadScript(ptr<File> file) = 0;

	/// Unregister instance of object if exposed to script.
	/** Invalidates object instances in script (if they exist), and releases a reference.
	Invalidated instances should not be touched by script ever. */
	virtual void ReclaimInstance(RefCounted* object) = 0;
};

END_INANITY_SCRIPT

#endif
<|endoftext|>


<commit_before>/* Copyright 2015 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

// See docs in ../ops/math_ops.cc.

#define EIGEN_USE_THREADS

#include "tensorflow/core/kernels/aggregate_ops.h"
#include "tensorflow/core/kernels/aggregate_ops_cpu.h"

#include "tensorflow/core/framework/numeric_op.h"
#include "tensorflow/core/framework/register_types.h"
#include "tensorflow/core/lib/gtl/inlined_vector.h"
#include "tensorflow/core/platform/logging.h"

namespace tensorflow {

typedef Eigen::ThreadPoolDevice CPUDevice;
typedef Eigen::GpuDevice GPUDevice;
#ifdef TENSORFLOW_USE_SYCL
typedef Eigen::SyclDevice SYCLDevice;
#endif // TENSORFLOW_USE_SYCL

template <typename Device, typename T>
class AddNOp : public OpKernel {
 public:
  explicit AddNOp(OpKernelConstruction* context) : OpKernel(context) {}

  void Compute(OpKernelContext* ctx) override {
    if (!ctx->ValidateInputsAreSameShape(this)) return;

    const Tensor& input0 = ctx->input(0);
    const int num = ctx->num_inputs();

    if (num == 1) {
      ctx->set_output(0, input0);
      return;
    }

    Tensor* output = nullptr;
    gtl::InlinedVector<int, 8> input_indices(num);
    std::iota(input_indices.begin(), input_indices.end(), 0);
    OP_REQUIRES_OK(ctx, ctx->forward_input_or_allocate_output(
                            input_indices, 0, input0.shape(), &output));
    auto To = output->flat<T>();

#define I(IDX) ctx->input(IDX).flat<T>()

#if defined(__ANDROID_TYPES_SLIM__)
    // On Android by default,we only support additions of two arguments, so we
    // can reduce the number of template instantiations.
    OP_REQUIRES(ctx, num == 2,
                errors::InvalidArgument("Only additions of two arguments "
                                        "supported. Num inputs: ",
                                        num));
    functor::Add2Functor<Device, T> functor2;
    functor2(ctx->template eigen_device<Device>(), To, I(0), I(1));
#else
    static const int kWidth = 8;
    int r = num % kWidth;

    switch (r) {
      case 2: {
        functor::Add2Functor<Device, T> functor2;
        functor2(ctx->template eigen_device<Device>(), To, I(0), I(1));
        break;
      }
      case 3: {
        functor::Add3Functor<Device, T> functor3;
        functor3(ctx->template eigen_device<Device>(), To, I(0), I(1), I(2));
        break;
      }
      case 4: {
        functor::Add4Functor<Device, T> functor4;
        functor4(ctx->template eigen_device<Device>(), To, I(0), I(1), I(2),
                 I(3));
        break;
      }
      case 5: {
        functor::Add5Functor<Device, T> functor5;
        functor5(ctx->template eigen_device<Device>(), To, I(0), I(1), I(2),
                 I(3), I(4));
        break;
      }
      case 6: {
        functor::Add6Functor<Device, T> functor6;
        functor6(ctx->template eigen_device<Device>(), To, I(0), I(1), I(2),
                 I(3), I(4), I(5));
        break;
      }
      case 7: {
        functor::Add7Functor<Device, T> functor7;
        functor7(ctx->template eigen_device<Device>(), To, I(0), I(1), I(2),
                 I(3), I(4), I(5), I(6));
        break;
      }
      case 0: {
        functor::Add8Functor<Device, T> functor8;
        functor8(ctx->template eigen_device<Device>(), To, I(0), I(1), I(2),
                 I(3), I(4), I(5), I(6), I(7));
        r = 8;
        break;
      }
      case 1: {
        functor::Add9Functor<Device, T> functor9;
        functor9(ctx->template eigen_device<Device>(), To, I(0), I(1), I(2),
                 I(3), I(4), I(5), I(6), I(7), I(8));
        r = 9;
        break;
      }
    }

    for (; r < num; r += kWidth) {
      functor::Add8pFunctor<Device, T> functor8p;
      functor8p(ctx->template eigen_device<Device>(), To, I(r), I(r + 1),
                I(r + 2), I(r + 3), I(r + 4), I(r + 5), I(r + 6), I(r + 7));
    }
#endif  // defined(__ANDROID_TYPES_SLIM__)

#undef I
  }
};

#define REGISTER_ADDN(type, dev)                                   \
  REGISTER_KERNEL_BUILDER(                                         \
      Name("AddN").Device(DEVICE_##dev).TypeConstraint<type>("T"), \
      AddNOp<dev##Device, type>)

#define REGISTER_ADDN_CPU(type) REGISTER_ADDN(type, CPU)

TF_CALL_NUMBER_TYPES(REGISTER_ADDN_CPU);
#undef REGISTER_ADDN_CPU

#if GOOGLE_CUDA
REGISTER_ADDN(Eigen::half, GPU);
REGISTER_ADDN(float, GPU);
REGISTER_ADDN(double, GPU);

// A special GPU kernel for int32.
// TODO(b/25387198): Also enable int32 in device memory. This kernel
// registration requires all int32 inputs and outputs to be in host memory.
REGISTER_KERNEL_BUILDER(Name("AddN")
                            .Device(DEVICE_GPU)
                            .TypeConstraint<int32>("T")
                            .HostMemory("inputs")
                            .HostMemory("sum"),
                        AddNOp<CPUDevice, int32>);
#endif  // GOOGLE_CUDA

#ifdef TENSORFLOW_USE_SYCL
REGISTER_ADDN(float, SYCL);
REGISTER_ADDN(double, SYCL);

// A special GPU kernel for int32.
// TODO(b/25387198): Also enable int32 in device memory. This kernel
// registration requires all int32 inputs and outputs to be in host memory.
REGISTER_KERNEL_BUILDER(Name("AddN")
                            .Device(DEVICE_SYCL)
                            .TypeConstraint<int32>("T")
                            .HostMemory("inputs")
                            .HostMemory("sum"),
                        AddNOp<CPUDevice, int32>);
#endif // TENSORFLOW_USE_SYCL

#undef REGISTER_ADDN

}  // namespace tensorflow
<commit_msg>Fix use of `std::iota()` in MSVC build. Change: 148380039<commit_after>/* Copyright 2015 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

// See docs in ../ops/math_ops.cc.

#define EIGEN_USE_THREADS

#include <numeric>

#include "tensorflow/core/kernels/aggregate_ops.h"
#include "tensorflow/core/kernels/aggregate_ops_cpu.h"

#include "tensorflow/core/framework/numeric_op.h"
#include "tensorflow/core/framework/register_types.h"
#include "tensorflow/core/lib/gtl/inlined_vector.h"
#include "tensorflow/core/platform/logging.h"

namespace tensorflow {

typedef Eigen::ThreadPoolDevice CPUDevice;
typedef Eigen::GpuDevice GPUDevice;
#ifdef TENSORFLOW_USE_SYCL
typedef Eigen::SyclDevice SYCLDevice;
#endif // TENSORFLOW_USE_SYCL

template <typename Device, typename T>
class AddNOp : public OpKernel {
 public:
  explicit AddNOp(OpKernelConstruction* context) : OpKernel(context) {}

  void Compute(OpKernelContext* ctx) override {
    if (!ctx->ValidateInputsAreSameShape(this)) return;

    const Tensor& input0 = ctx->input(0);
    const int num = ctx->num_inputs();

    if (num == 1) {
      ctx->set_output(0, input0);
      return;
    }

    Tensor* output = nullptr;
    gtl::InlinedVector<int, 8> input_indices(num);
    std::iota(input_indices.begin(), input_indices.end(), 0);
    OP_REQUIRES_OK(ctx, ctx->forward_input_or_allocate_output(
                            input_indices, 0, input0.shape(), &output));
    auto To = output->flat<T>();

#define I(IDX) ctx->input(IDX).flat<T>()

#if defined(__ANDROID_TYPES_SLIM__)
    // On Android by default,we only support additions of two arguments, so we
    // can reduce the number of template instantiations.
    OP_REQUIRES(ctx, num == 2,
                errors::InvalidArgument("Only additions of two arguments "
                                        "supported. Num inputs: ",
                                        num));
    functor::Add2Functor<Device, T> functor2;
    functor2(ctx->template eigen_device<Device>(), To, I(0), I(1));
#else
    static const int kWidth = 8;
    int r = num % kWidth;

    switch (r) {
      case 2: {
        functor::Add2Functor<Device, T> functor2;
        functor2(ctx->template eigen_device<Device>(), To, I(0), I(1));
        break;
      }
      case 3: {
        functor::Add3Functor<Device, T> functor3;
        functor3(ctx->template eigen_device<Device>(), To, I(0), I(1), I(2));
        break;
      }
      case 4: {
        functor::Add4Functor<Device, T> functor4;
        functor4(ctx->template eigen_device<Device>(), To, I(0), I(1), I(2),
                 I(3));
        break;
      }
      case 5: {
        functor::Add5Functor<Device, T> functor5;
        functor5(ctx->template eigen_device<Device>(), To, I(0), I(1), I(2),
                 I(3), I(4));
        break;
      }
      case 6: {
        functor::Add6Functor<Device, T> functor6;
        functor6(ctx->template eigen_device<Device>(), To, I(0), I(1), I(2),
                 I(3), I(4), I(5));
        break;
      }
      case 7: {
        functor::Add7Functor<Device, T> functor7;
        functor7(ctx->template eigen_device<Device>(), To, I(0), I(1), I(2),
                 I(3), I(4), I(5), I(6));
        break;
      }
      case 0: {
        functor::Add8Functor<Device, T> functor8;
        functor8(ctx->template eigen_device<Device>(), To, I(0), I(1), I(2),
                 I(3), I(4), I(5), I(6), I(7));
        r = 8;
        break;
      }
      case 1: {
        functor::Add9Functor<Device, T> functor9;
        functor9(ctx->template eigen_device<Device>(), To, I(0), I(1), I(2),
                 I(3), I(4), I(5), I(6), I(7), I(8));
        r = 9;
        break;
      }
    }

    for (; r < num; r += kWidth) {
      functor::Add8pFunctor<Device, T> functor8p;
      functor8p(ctx->template eigen_device<Device>(), To, I(r), I(r + 1),
                I(r + 2), I(r + 3), I(r + 4), I(r + 5), I(r + 6), I(r + 7));
    }
#endif  // defined(__ANDROID_TYPES_SLIM__)

#undef I
  }
};

#define REGISTER_ADDN(type, dev)                                   \
  REGISTER_KERNEL_BUILDER(                                         \
      Name("AddN").Device(DEVICE_##dev).TypeConstraint<type>("T"), \
      AddNOp<dev##Device, type>)

#define REGISTER_ADDN_CPU(type) REGISTER_ADDN(type, CPU)

TF_CALL_NUMBER_TYPES(REGISTER_ADDN_CPU);
#undef REGISTER_ADDN_CPU

#if GOOGLE_CUDA
REGISTER_ADDN(Eigen::half, GPU);
REGISTER_ADDN(float, GPU);
REGISTER_ADDN(double, GPU);

// A special GPU kernel for int32.
// TODO(b/25387198): Also enable int32 in device memory. This kernel
// registration requires all int32 inputs and outputs to be in host memory.
REGISTER_KERNEL_BUILDER(Name("AddN")
                            .Device(DEVICE_GPU)
                            .TypeConstraint<int32>("T")
                            .HostMemory("inputs")
                            .HostMemory("sum"),
                        AddNOp<CPUDevice, int32>);
#endif  // GOOGLE_CUDA

#ifdef TENSORFLOW_USE_SYCL
REGISTER_ADDN(float, SYCL);
REGISTER_ADDN(double, SYCL);

// A special GPU kernel for int32.
// TODO(b/25387198): Also enable int32 in device memory. This kernel
// registration requires all int32 inputs and outputs to be in host memory.
REGISTER_KERNEL_BUILDER(Name("AddN")
                            .Device(DEVICE_SYCL)
                            .TypeConstraint<int32>("T")
                            .HostMemory("inputs")
                            .HostMemory("sum"),
                        AddNOp<CPUDevice, int32>);
#endif // TENSORFLOW_USE_SYCL

#undef REGISTER_ADDN

}  // namespace tensorflow
<|endoftext|>


<commit_before>// RUN: %clang_analyze_cc1 -triple x86_64-unknown-linux -analyzer-checker=debug.DumpCFG %s > %t 2>&1
// RUN: FileCheck --input-file=%t %s
// RUN: %clang_analyze_cc1 -triple x86_64-unknown-linux -analyzer-checker=core,debug.ExprInspection -std=c++14 -verify %s

void clang_analyzer_eval(bool);

int global;

namespace variant_0 {
// This variant of the code works correctly. Function foo() is not a template
// function. Note that there are two destructors within foo().

class A {
public:
  ~A() { ++global; }
};

class B {
  A a;
};

// CHECK: void foo(int)
// CHECK:       [B1]
// CHECK-NEXT:    1:  (CXXConstructExpr, [B1.2], class variant_0::B)
// CHECK-NEXT:    2: variant_0::B i;
// CHECK-NEXT:    3: operator=
// CHECK-NEXT:    4: [B1.3] (ImplicitCastExpr, FunctionToPointerDecay, class variant_0::B &(*)(class variant_0::B &&) noexcept)
// CHECK-NEXT:    5: i
// CHECK-NEXT:    6: {} (CXXConstructExpr, [B1.7], [B1.8], class variant_0::B)
// CHECK-NEXT:    7: [B1.6] (BindTemporary)
// CHECK-NEXT:    8: [B1.7]
// CHECK-NEXT:    9: [B1.5] = [B1.8] (OperatorCall)
// CHECK-NEXT:   10: ~variant_0::B() (Temporary object destructor)
// CHECK-NEXT:   11: [B1.2].~B() (Implicit destructor)
void foo(int) {
  B i;
  i = {};
}

void bar() {
  global = 0;
  foo(1);
  clang_analyzer_eval(global == 2); // expected-warning{{TRUE}}
}

} // end namespace variant_0

namespace variant_1 {
// Suddenly, if we turn foo() into a template, we are missing a
// CXXBindTemporaryExpr in the AST, and therefore we're missing a
// temporary destructor in the CFG.

class A {
public:
  ~A() { ++global; }
};

class B {
  A a;
};

// FIXME: Find the construction context for {} and enforce the temporary
// destructor.
// CHECK: template<> void foo<int>(int)
// CHECK:       [B1]
// CHECK-NEXT:    1:  (CXXConstructExpr, [B1.2], class variant_1::B)
// CHECK-NEXT:    2: variant_1::B i;
// CHECK-NEXT:    3: operator=
// CHECK-NEXT:    4: [B1.3] (ImplicitCastExpr, FunctionToPointerDecay, class variant_1::B &(*)(class variant_1::B &&) noexcept)
// CHECK-NEXT:    5: i
// CHECK-NEXT:    6: {} (CXXConstructExpr, class variant_1::B)
// CHECK-NEXT:    7: [B1.6]
// CHECK-NEXT:    8: [B1.5] = [B1.7] (OperatorCall)
// CHECK-NEXT:    9: [B1.2].~B() (Implicit destructor)
template <typename T> void foo(T) {
  B i;
  i = {};
}

void bar() {
  global = 0;
  foo(1);
  // FIXME: Should be TRUE, i.e. we should call (and inline) two destructors.
  clang_analyzer_eval(global == 2); // expected-warning{{UNKNOWN}}
}

} // end namespace variant_1

namespace variant_2 {
// Making field 'a' in class 'B' public turns the class into an aggregate.
// In this case there is no constructor at {} - only an aggregate
// initialization. Aggregate initialization is unsupported for now.

class A {
public:
  ~A() { ++global; }
};

class B {
public:
  A a;
};

// CHECK: template<> void foo<int>(int)
// CHECK:       [B1]
// CHECK-NEXT:    1:  (CXXConstructExpr, [B1.2], class variant_2::B)
// CHECK-NEXT:    2: variant_2::B i;
// CHECK-NEXT:    3: operator=
// CHECK-NEXT:    4: [B1.3] (ImplicitCastExpr, FunctionToPointerDecay, class variant_2::B &(*)(class variant_2::B &&) noexcept)
// CHECK-NEXT:    5: i
// CHECK-NEXT:    6: {}
// CHECK-NEXT:    7: {}
// CHECK-NEXT:    8: [B1.7] (BindTemporary)
// CHECK-NEXT:    9: [B1.8]
// CHECK-NEXT:   10: [B1.5] = [B1.9] (OperatorCall)
// CHECK-NEXT:   11: ~variant_2::B() (Temporary object destructor)
// CHECK-NEXT:   12: [B1.2].~B() (Implicit destructor)
template <typename T> void foo(T) {
  B i;
  i = {};
}

void bar() {
  global = 0;
  foo(1);
  // FIXME: Should be TRUE, i.e. we should call (and inline) two destructors.
  clang_analyzer_eval(global == 2); // expected-warning{{UNKNOWN}}
}

} // end namespace variant_2
<commit_msg>[analyzer][test] Set C++14 as language standard for test depending on new features<commit_after>// RUN: %clang_analyze_cc1 -triple x86_64-unknown-linux -analyzer-checker=debug.DumpCFG -std=c++14 %s > %t 2>&1
// RUN: FileCheck --input-file=%t %s
// RUN: %clang_analyze_cc1 -triple x86_64-unknown-linux -analyzer-checker=core,debug.ExprInspection -std=c++14 -verify %s

void clang_analyzer_eval(bool);

int global;

namespace variant_0 {
// This variant of the code works correctly. Function foo() is not a template
// function. Note that there are two destructors within foo().

class A {
public:
  ~A() { ++global; }
};

class B {
  A a;
};

// CHECK: void foo(int)
// CHECK:       [B1]
// CHECK-NEXT:    1:  (CXXConstructExpr, [B1.2], class variant_0::B)
// CHECK-NEXT:    2: variant_0::B i;
// CHECK-NEXT:    3: operator=
// CHECK-NEXT:    4: [B1.3] (ImplicitCastExpr, FunctionToPointerDecay, class variant_0::B &(*)(class variant_0::B &&) noexcept)
// CHECK-NEXT:    5: i
// CHECK-NEXT:    6: {} (CXXConstructExpr, [B1.7], [B1.8], class variant_0::B)
// CHECK-NEXT:    7: [B1.6] (BindTemporary)
// CHECK-NEXT:    8: [B1.7]
// CHECK-NEXT:    9: [B1.5] = [B1.8] (OperatorCall)
// CHECK-NEXT:   10: ~variant_0::B() (Temporary object destructor)
// CHECK-NEXT:   11: [B1.2].~B() (Implicit destructor)
void foo(int) {
  B i;
  i = {};
}

void bar() {
  global = 0;
  foo(1);
  clang_analyzer_eval(global == 2); // expected-warning{{TRUE}}
}

} // end namespace variant_0

namespace variant_1 {
// Suddenly, if we turn foo() into a template, we are missing a
// CXXBindTemporaryExpr in the AST, and therefore we're missing a
// temporary destructor in the CFG.

class A {
public:
  ~A() { ++global; }
};

class B {
  A a;
};

// FIXME: Find the construction context for {} and enforce the temporary
// destructor.
// CHECK: template<> void foo<int>(int)
// CHECK:       [B1]
// CHECK-NEXT:    1:  (CXXConstructExpr, [B1.2], class variant_1::B)
// CHECK-NEXT:    2: variant_1::B i;
// CHECK-NEXT:    3: operator=
// CHECK-NEXT:    4: [B1.3] (ImplicitCastExpr, FunctionToPointerDecay, class variant_1::B &(*)(class variant_1::B &&) noexcept)
// CHECK-NEXT:    5: i
// CHECK-NEXT:    6: {} (CXXConstructExpr, class variant_1::B)
// CHECK-NEXT:    7: [B1.6]
// CHECK-NEXT:    8: [B1.5] = [B1.7] (OperatorCall)
// CHECK-NEXT:    9: [B1.2].~B() (Implicit destructor)
template <typename T> void foo(T) {
  B i;
  i = {};
}

void bar() {
  global = 0;
  foo(1);
  // FIXME: Should be TRUE, i.e. we should call (and inline) two destructors.
  clang_analyzer_eval(global == 2); // expected-warning{{UNKNOWN}}
}

} // end namespace variant_1

namespace variant_2 {
// Making field 'a' in class 'B' public turns the class into an aggregate.
// In this case there is no constructor at {} - only an aggregate
// initialization. Aggregate initialization is unsupported for now.

class A {
public:
  ~A() { ++global; }
};

class B {
public:
  A a;
};

// CHECK: template<> void foo<int>(int)
// CHECK:       [B1]
// CHECK-NEXT:    1:  (CXXConstructExpr, [B1.2], class variant_2::B)
// CHECK-NEXT:    2: variant_2::B i;
// CHECK-NEXT:    3: operator=
// CHECK-NEXT:    4: [B1.3] (ImplicitCastExpr, FunctionToPointerDecay, class variant_2::B &(*)(class variant_2::B &&) noexcept)
// CHECK-NEXT:    5: i
// CHECK-NEXT:    6: {}
// CHECK-NEXT:    7: {}
// CHECK-NEXT:    8: [B1.7] (BindTemporary)
// CHECK-NEXT:    9: [B1.8]
// CHECK-NEXT:   10: [B1.5] = [B1.9] (OperatorCall)
// CHECK-NEXT:   11: ~variant_2::B() (Temporary object destructor)
// CHECK-NEXT:   12: [B1.2].~B() (Implicit destructor)
template <typename T> void foo(T) {
  B i;
  i = {};
}

void bar() {
  global = 0;
  foo(1);
  // FIXME: Should be TRUE, i.e. we should call (and inline) two destructors.
  clang_analyzer_eval(global == 2); // expected-warning{{UNKNOWN}}
}

} // end namespace variant_2
<|endoftext|>


<commit_before>#pragma once
//=====================================================================//
/*!	@file
	@brief	RX24T グループ A/D 制御 @n
			Copyright 2016 Kunihito Hiramatsu
	@author	平松邦仁 (hira@rvf-rc45.net)
*/
//=====================================================================//
#include "common/renesas.hpp"
#include "common/vect.h"
#include "RX24T/port_map.hpp"
#include "RX24T/power_cfg.hpp"

/// F_PCKD は変換パラメーター計算で必要で、設定が無いとエラーにします。
#ifndef F_PCKD
#  error "adc_io.hpp requires F_PCKD to be defined"
#endif

namespace device {

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  A/D 制御クラス
		@param[in]	ADCU	A/D チャネル・ユニット
		@param[in]	TASK	割り込みタスク
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <class ADCU, class TASK>
	class adc_io {
	public:

		typedef ADCU value_type;

		//-----------------------------------------------------------------//
		/*!
			@brief	変換モード
		 */
		//-----------------------------------------------------------------//
		enum class cnv_type : uint8_t {

		};

	private:
		static TASK task_;

		static INTERRUPT_FUNC void adi_task_()
		{
			task_();
		}

		uint8_t	level_;

		static inline void sleep_() { asm("nop"); }

	public:
		//-----------------------------------------------------------------//
		/*!
			@brief	コンストラクター
		 */
		//-----------------------------------------------------------------//
		adc_io() : level_(0) { }

		//-----------------------------------------------------------------//
		/*!
			@brief	スタート
			@param[in]	ana		アナログ入力
			@param[in]	level	割り込みレベル、０の場合はポーリング
			@return 成功なら「true」
		 */
		//-----------------------------------------------------------------//
		bool start(typename ADCU::analog ana, uint8_t level = 0)
		{
			level_ = level;

			// 基本変換時間（１マイクロ秒）＋マージン
			uint32_t n = F_PCKD / 1000000 + 10;
			if(n > 255) return false;

			power_cfg::turn(ADCU::get_peripheral());
			ADCU::enable(ana);
			ADCU::ADANSA.set(ana);
			ADCU::ADSSTR.set(ana, n);

			return true;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief	スキャン開始
		 */
		//-----------------------------------------------------------------//
		void scan() {
			if(level_) {
				set_interrupt_task(adi_task_, static_cast<uint32_t>(ADCU::get_vec()));
				icu_mgr::set_level(ADCU::get_peripheral(), level_);
				ADCU::ADCSR = ADCU::ADCSR.ADST.b() | ADCU::ADCSR.ADIE.b();
			} else {
				ADCU::ADCSR = ADCU::ADCSR.ADST.b();
			}
		}

		//-----------------------------------------------------------------//
		/*!
			@brief	変換状態の取得
			@return 変換中なら「true」
		 */
		//-----------------------------------------------------------------//
		bool get_state() const {
			return ADCU::ADCSR.ADST();
		}

		//-----------------------------------------------------------------//
		/*!
			@brief	読み込み同期
		 */
		//-----------------------------------------------------------------//
		void sync() const {
			while(ADCU::ADCSR.ADST() != 0) sleep_();
		}

		//-----------------------------------------------------------------//
		/*!
			@brief	A/D 変換結果を取得
			@param[in]	an	変換チャネル
			@return 変換結果（上位１０ビットが有効な値）
		 */
		//-----------------------------------------------------------------//
		uint16_t get(typename ADCU::analog an) const {
			return ADCU::ADDR(an);
		}
	};

//	template<class ADCU, class TASK>
//	volatile uint16_t adc_io<ADCU, TASK>::value_[ADCU::analog_num_];
}
<commit_msg>fix template static class<commit_after>#pragma once
//=====================================================================//
/*!	@file
	@brief	RX24T グループ A/D 制御 @n
			Copyright 2016 Kunihito Hiramatsu
	@author	平松邦仁 (hira@rvf-rc45.net)
*/
//=====================================================================//
#include "common/renesas.hpp"
#include "common/vect.h"
#include "RX24T/port_map.hpp"
#include "RX24T/power_cfg.hpp"

/// F_PCKD は変換パラメーター計算で必要で、設定が無いとエラーにします。
#ifndef F_PCKD
#  error "adc_io.hpp requires F_PCKD to be defined"
#endif

namespace device {

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  A/D 制御クラス
		@param[in]	ADCU	A/D チャネル・ユニット
		@param[in]	TASK	割り込みタスク
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <class ADCU, class TASK>
	class adc_io {
	public:

		typedef ADCU value_type;

		//-----------------------------------------------------------------//
		/*!
			@brief	変換モード
		 */
		//-----------------------------------------------------------------//
		enum class cnv_type : uint8_t {

		};

	private:
		static TASK task_;

		static INTERRUPT_FUNC void adi_task_()
		{
			task_();
		}

		uint8_t	level_;

		static inline void sleep_() { asm("nop"); }

	public:
		//-----------------------------------------------------------------//
		/*!
			@brief	コンストラクター
		 */
		//-----------------------------------------------------------------//
		adc_io() : level_(0) { }

		//-----------------------------------------------------------------//
		/*!
			@brief	スタート
			@param[in]	ana		アナログ入力
			@param[in]	level	割り込みレベル、０の場合はポーリング
			@return 成功なら「true」
		 */
		//-----------------------------------------------------------------//
		bool start(typename ADCU::analog ana, uint8_t level = 0)
		{
			level_ = level;

			// 基本変換時間（１マイクロ秒）＋マージン
			uint32_t n = F_PCKD / 1000000 + 10;
			if(n > 255) return false;

			power_cfg::turn(ADCU::get_peripheral());
			ADCU::enable(ana);
			ADCU::ADANSA.set(ana);
			ADCU::ADSSTR.set(ana, n);

			return true;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief	スキャン開始
		 */
		//-----------------------------------------------------------------//
		void scan() {
			if(level_) {
				set_interrupt_task(adi_task_, static_cast<uint32_t>(ADCU::get_vec()));
				icu_mgr::set_level(ADCU::get_peripheral(), level_);
				ADCU::ADCSR = ADCU::ADCSR.ADST.b() | ADCU::ADCSR.ADIE.b();
			} else {
				ADCU::ADCSR = ADCU::ADCSR.ADST.b();
			}
		}

		//-----------------------------------------------------------------//
		/*!
			@brief	変換状態の取得
			@return 変換中なら「true」
		 */
		//-----------------------------------------------------------------//
		bool get_state() const {
			return ADCU::ADCSR.ADST();
		}

		//-----------------------------------------------------------------//
		/*!
			@brief	読み込み同期
		 */
		//-----------------------------------------------------------------//
		void sync() const {
			while(ADCU::ADCSR.ADST() != 0) sleep_();
		}

		//-----------------------------------------------------------------//
		/*!
			@brief	A/D 変換結果を取得
			@param[in]	an	変換チャネル
			@return 変換結果（上位１０ビットが有効な値）
		 */
		//-----------------------------------------------------------------//
		uint16_t get(typename ADCU::analog an) const {
			return ADCU::ADDR(an);
		}
	};

	template <class ADCU, class TASK>
	TASK adc_io<ADCU, TASK>::task_;
}
<|endoftext|>


<commit_before>/*
 * Copyright 2014 David Moreno
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#pragma once

#include <string>
#include <vector>
#include <functional>
#include <unordered_map>

#include "symbol.hpp"
// #include "program.hpp"

namespace loglang{
	class Program;

	class Context{
		std::function<void (const std::string &output)> _output;
		std::unordered_map<std::string, Symbol> symboltable;
		std::unordered_map<std::string, std::shared_ptr<Program>> glob_dependencies_programs;
		std::unordered_map<std::string, std::shared_ptr<Program>> programs;
		std::unordered_map<std::string, std::function<any (Context &, const std::vector<any> &)>> functions;
	public:
		Context();
		void feed_secure(std::string data);
		void feed(std::string data);
		void set_output(std::function<void (const std::string &output)> &&);
		void output(const std::string &str){ _output(str); }
		void output(const std::string &str, const std::string &str2);
		Symbol &get_value(const std::string &key);

		/// Returns the resolved glob values.
		any get_glob_values(const std::string &glob);
		std::vector<Symbol*> symboltable_filter(const std::string &glob);

		void register_function(std::string fnname, std::function<any (Context &, const std::vector<any> &)> f);
		any fn(const std::string &fname, const std::vector<any> &args);

		void debug_values();
	};
};
<commit_msg>Enable shared from this at context.<commit_after>/*
 * Copyright 2014 David Moreno
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#pragma once

#include <string>
#include <vector>
#include <functional>
#include <unordered_map>

#include "symbol.hpp"
// #include "program.hpp"

namespace loglang{
	class Program;

	class Context : public std::enable_shared_from_this<Context>{
		std::function<void (const std::string &output)> _output;
		std::unordered_map<std::string, Symbol> symboltable;
		std::unordered_map<std::string, std::shared_ptr<Program>> glob_dependencies_programs;
		std::unordered_map<std::string, std::shared_ptr<Program>> programs;
		std::unordered_map<std::string, std::function<any (Context &, const std::vector<any> &)>> functions;
	public:
		Context();
		void feed_secure(std::string data);
		void feed(std::string data);
		void set_output(std::function<void (const std::string &output)> &&);
		void output(const std::string &str){ _output(str); }
		void output(const std::string &str, const std::string &str2);
		Symbol &get_value(const std::string &key);

		/// Returns the resolved glob values.
		any get_glob_values(const std::string &glob);
		std::vector<Symbol*> symboltable_filter(const std::string &glob);

		void register_function(std::string fnname, std::function<any (Context &, const std::vector<any> &)> f);
		any fn(const std::string &fname, const std::vector<any> &args);

		void debug_values();
	};
};
<|endoftext|>


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

#include <gtest/gtest.h>

#include <vector>

#include <mesos/authentication/http/basic_authenticator_factory.hpp>

#include <mesos/module/http_authenticator.hpp>

#include <process/authenticator.hpp>
#include <process/gtest.hpp>
#include <process/http.hpp>

#include <stout/base64.hpp>

#include "tests/mesos.hpp"
#include "tests/module.hpp"

using namespace process;

using std::vector;

namespace process {
namespace http {

bool operator==(const Forbidden &left, const Forbidden &right)
{
  return left.body == right.body;
}

bool operator==(const Unauthorized &left, const Unauthorized &right)
{
  return left.body == right.body &&
         left.headers.get("WWW-Authenticate") ==
             right.headers.get("WWW-Authenticate");
}

namespace authentication {

bool operator==(
    const AuthenticationResult& left,
    const AuthenticationResult& right)
{
  return left.principal == right.principal &&
      left.unauthorized == right.unauthorized &&
      left.forbidden == right.forbidden;
}

} // namespace authentication {

} // namespace http {
} // namespace process {

namespace mesos {
namespace internal {
namespace tests {

using mesos::http::authentication::BasicAuthenticatorFactory;

using process::http::Request;
using process::http::Unauthorized;

using process::http::authentication::Authenticator;
using process::http::authentication::Principal;
using process::http::authentication::AuthenticationResult;

static const std::string REALM = "tatooine";

static Parameters createBasicAuthenticatorParameters(
    const Option<std::string>& realm,
    const Option<Credentials>& credentials)
{
  Parameters parameters;

  if (realm.isSome()) {
    Parameter* parameter = parameters.add_parameter();
    parameter->set_key("authentication_realm");
    parameter->set_value(realm.get());
  }

  if (credentials.isSome()) {
    Parameter* parameter = parameters.add_parameter();
    parameter->set_key("credentials");
    parameter->set_value(
        stringify(JSON::protobuf(credentials->credentials())));
  }

  return parameters;
}

template <typename T>
class HttpAuthenticationTest : public MesosTest {};

typedef ::testing::Types<
// TODO(josephw): Modules are not supported on Windows (MESOS-5994).
#ifndef __WINDOWS__
    tests::Module<Authenticator, TestHttpBasicAuthenticator>,
#endif // __WINDOWS__
    BasicAuthenticatorFactory> HttpAuthenticatorTypes;

TYPED_TEST_CASE(HttpAuthenticationTest, HttpAuthenticatorTypes);

// Tests the HTTP basic authenticator without credentials.
// Full HTTP stack tests are located in libprocess-tests.
TYPED_TEST(HttpAuthenticationTest, BasicWithoutCredentialsTest)
{
  Parameters parameters = createBasicAuthenticatorParameters(REALM, None());

  Try<Authenticator*> create = TypeParam::create(parameters);
  ASSERT_SOME(create);
  Owned<Authenticator> authenticator(create.get());

  EXPECT_EQ("Basic", authenticator->scheme());

  // No credentials given.
  {
    AuthenticationResult unauthorized;
    unauthorized.unauthorized =
      Unauthorized({"Basic realm=\"" + REALM + "\""});

    Request request;

    AWAIT_EXPECT_EQ(unauthorized, authenticator->authenticate(request));
  }

  // Unrecognized credentials.
  {
    Request request;
    request.headers.put(
        "Authorization",
        "Basic " + base64::encode("user:password"));

    AuthenticationResult unauthorized;
    unauthorized.unauthorized =
      Unauthorized({"Basic realm=\"" + REALM + "\""});

    AWAIT_EXPECT_EQ(unauthorized, authenticator->authenticate(request));
  }
}

// Tests the HTTP basic authenticator with credentials.
// Full HTTP stack tests are located in libprocess-tests.
TYPED_TEST(HttpAuthenticationTest, BasicWithCredentialsTest)
{
  Credentials credentials;
  Credential* credential = credentials.add_credentials();
  credential->set_principal("user");
  credential->set_secret("password");

  Parameters parameters =
    createBasicAuthenticatorParameters(REALM, credentials);

  Try<Authenticator*> create = TypeParam::create(parameters);
  ASSERT_SOME(create);
  Owned<Authenticator> authenticator(create.get());

  EXPECT_EQ("Basic", authenticator->scheme());

  // No credentials given.
  {
    Request request;

    AuthenticationResult unauthorized;
    unauthorized.unauthorized =
      Unauthorized({"Basic realm=\"" + REALM + "\""});

    AWAIT_EXPECT_EQ(unauthorized, authenticator->authenticate(request));
  }

  // Wrong credentials given.
  {
    Request request;

    request.headers.put(
        "Authorization",
        "Basic " + base64::encode("wronguser:wrongpassword"));

    AuthenticationResult unauthorized;
    unauthorized.unauthorized =
      Unauthorized({"Basic realm=\"" + REALM + "\""});

    AWAIT_EXPECT_EQ(unauthorized, authenticator->authenticate(request));
  }

  // Right credentials given.
  {
    Request request;

    AuthenticationResult result;
    result.principal = Principal("user");

    request.headers.put(
        "Authorization",
        "Basic " + base64::encode("user:password"));

    AWAIT_EXPECT_EQ(result, authenticator->authenticate(request));
  }
}

// Tests that the HTTP basic authenticator will return an error if it is given
// module parameters that don't contain an authentication realm.
TYPED_TEST(HttpAuthenticationTest, BasicWithoutRealm)
{
  Credentials credentials;
  Credential* credential = credentials.add_credentials();
  credential->set_principal("user");
  credential->set_secret("password");

  Parameters parameters =
    createBasicAuthenticatorParameters(None(), credentials);

  Try<Authenticator*> create = TypeParam::create(parameters);

  ASSERT_ERROR(create);
}

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

#include <gtest/gtest.h>

#include <vector>

#include <mesos/authentication/http/basic_authenticator_factory.hpp>
#include <mesos/authentication/http/combined_authenticator.hpp>

#include <mesos/module/http_authenticator.hpp>

#include <process/authenticator.hpp>
#include <process/gtest.hpp>
#include <process/http.hpp>

#include <stout/base64.hpp>

#include "tests/mesos.hpp"
#include "tests/module.hpp"

using namespace process;

using std::string;
using std::vector;

namespace process {
namespace http {

bool operator==(const Forbidden &left, const Forbidden &right)
{
  return left.body == right.body;
}

bool operator==(const Unauthorized &left, const Unauthorized &right)
{
  return left.body == right.body &&
         left.headers.get("WWW-Authenticate") ==
             right.headers.get("WWW-Authenticate");
}

bool operator==(const URL &left, const URL &right)
{
  return left.scheme == right.scheme &&
         left.domain == right.domain &&
         left.ip == right.ip &&
         left.path == right.path &&
         left.query == right.query &&
         left.fragment == right.fragment &&
         left.port == right.port;
}

bool operator==(const Request &left, const Request &right)
{
  return left.headers == right.headers &&
         left.url == right.url &&
         left.method == right.method &&
         left.body == right.body;
}

namespace authentication {

bool operator==(
    const AuthenticationResult& left,
    const AuthenticationResult& right)
{
  return left.principal == right.principal &&
      left.unauthorized == right.unauthorized &&
      left.forbidden == right.forbidden;
}

} // namespace authentication {

} // namespace http {
} // namespace process {

namespace mesos {
namespace internal {
namespace tests {

using mesos::http::authentication::BasicAuthenticatorFactory;
using mesos::http::authentication::CombinedAuthenticator;

using process::http::Forbidden;
using process::http::Request;
using process::http::Unauthorized;

using process::http::authentication::Authenticator;
using process::http::authentication::AuthenticationResult;
using process::http::authentication::Principal;

static const string REALM = "tatooine";

static Parameters createBasicAuthenticatorParameters(
    const Option<string>& realm,
    const Option<Credentials>& credentials)
{
  Parameters parameters;

  if (realm.isSome()) {
    Parameter* parameter = parameters.add_parameter();
    parameter->set_key("authentication_realm");
    parameter->set_value(realm.get());
  }

  if (credentials.isSome()) {
    Parameter* parameter = parameters.add_parameter();
    parameter->set_key("credentials");
    parameter->set_value(
        stringify(JSON::protobuf(credentials->credentials())));
  }

  return parameters;
}

template <typename T>
class HttpAuthenticationTest : public MesosTest {};

typedef ::testing::Types<
// TODO(josephw): Modules are not supported on Windows (MESOS-5994).
#ifndef __WINDOWS__
    tests::Module<Authenticator, TestHttpBasicAuthenticator>,
#endif // __WINDOWS__
    BasicAuthenticatorFactory> HttpAuthenticatorTypes;

TYPED_TEST_CASE(HttpAuthenticationTest, HttpAuthenticatorTypes);

// Tests the HTTP basic authenticator without credentials.
// Full HTTP stack tests are located in libprocess-tests.
TYPED_TEST(HttpAuthenticationTest, BasicWithoutCredentialsTest)
{
  Parameters parameters = createBasicAuthenticatorParameters(REALM, None());

  Try<Authenticator*> create = TypeParam::create(parameters);
  ASSERT_SOME(create);
  Owned<Authenticator> authenticator(create.get());

  EXPECT_EQ("Basic", authenticator->scheme());

  // No credentials given.
  {
    AuthenticationResult unauthorized;
    unauthorized.unauthorized =
      Unauthorized({"Basic realm=\"" + REALM + "\""});

    Request request;

    AWAIT_EXPECT_EQ(unauthorized, authenticator->authenticate(request));
  }

  // Unrecognized credentials.
  {
    Request request;
    request.headers.put(
        "Authorization",
        "Basic " + base64::encode("user:password"));

    AuthenticationResult unauthorized;
    unauthorized.unauthorized =
      Unauthorized({"Basic realm=\"" + REALM + "\""});

    AWAIT_EXPECT_EQ(unauthorized, authenticator->authenticate(request));
  }
}

// Tests the HTTP basic authenticator with credentials.
// Full HTTP stack tests are located in libprocess-tests.
TYPED_TEST(HttpAuthenticationTest, BasicWithCredentialsTest)
{
  Credentials credentials;
  Credential* credential = credentials.add_credentials();
  credential->set_principal("user");
  credential->set_secret("password");

  Parameters parameters =
    createBasicAuthenticatorParameters(REALM, credentials);

  Try<Authenticator*> create = TypeParam::create(parameters);
  ASSERT_SOME(create);
  Owned<Authenticator> authenticator(create.get());

  EXPECT_EQ("Basic", authenticator->scheme());

  // No credentials given.
  {
    Request request;

    AuthenticationResult unauthorized;
    unauthorized.unauthorized =
      Unauthorized({"Basic realm=\"" + REALM + "\""});

    AWAIT_EXPECT_EQ(unauthorized, authenticator->authenticate(request));
  }

  // Wrong credentials given.
  {
    Request request;

    request.headers.put(
        "Authorization",
        "Basic " + base64::encode("wronguser:wrongpassword"));

    AuthenticationResult unauthorized;
    unauthorized.unauthorized =
      Unauthorized({"Basic realm=\"" + REALM + "\""});

    AWAIT_EXPECT_EQ(unauthorized, authenticator->authenticate(request));
  }

  // Right credentials given.
  {
    Request request;

    AuthenticationResult result;
    result.principal = Principal("user");

    request.headers.put(
        "Authorization",
        "Basic " + base64::encode("user:password"));

    AWAIT_EXPECT_EQ(result, authenticator->authenticate(request));
  }
}

// Tests that the HTTP basic authenticator will return an error if it is given
// module parameters that don't contain an authentication realm.
TYPED_TEST(HttpAuthenticationTest, BasicWithoutRealm)
{
  Credentials credentials;
  Credential* credential = credentials.add_credentials();
  credential->set_principal("user");
  credential->set_secret("password");

  Parameters parameters =
    createBasicAuthenticatorParameters(None(), credentials);

  Try<Authenticator*> create = TypeParam::create(parameters);

  ASSERT_ERROR(create);
}

class MockAuthenticator : public Authenticator
{
public:
  MockAuthenticator(string scheme) : mockScheme(scheme) {}

  MockAuthenticator(const MockAuthenticator& authenticator)
    : mockScheme(authenticator.mockScheme) {}

  MOCK_METHOD1(authenticate, Future<AuthenticationResult>(const Request&));

  virtual string scheme() const { return mockScheme; }

private:
  const string mockScheme;
};

AuthenticationResult createUnauthorized(MockAuthenticator& authenticator)
{
  AuthenticationResult result;
  result.unauthorized = Unauthorized(
      {authenticator.scheme() + " realm=\"" + REALM + "\""},
      authenticator.scheme() + " unauthorized");

  return result;
}

AuthenticationResult createForbidden(MockAuthenticator& authenticator)
{
  AuthenticationResult result;
  result.forbidden = Forbidden(authenticator.scheme() + " forbidden");

  return result;
}

AuthenticationResult createCombinedUnauthorized(
    vector<MockAuthenticator> authenticators)
{
  AuthenticationResult result;
  vector<string> headers;
  vector<string> bodies;

  foreach (const MockAuthenticator& authenticator, authenticators) {
    headers.push_back(authenticator.scheme() + " realm=\"" + REALM + "\"");
    bodies.push_back(
        "\"" + authenticator.scheme() + "\" authenticator returned:\n" +
        authenticator.scheme() + " unauthorized");
  }

  result.unauthorized = Unauthorized(
      {strings::join(",", headers)},
      strings::join("\n\n", bodies));

  return result;
}

AuthenticationResult createCombinedForbidden(
    vector<MockAuthenticator> authenticators)
{
  AuthenticationResult result;
  vector<string> bodies;

  foreach (const MockAuthenticator& authenticator, authenticators) {
    bodies.push_back(
        "\"" + authenticator.scheme() + "\" authenticator returned:\n" +
        authenticator.scheme() + " forbidden");
  }

  result.forbidden = Forbidden(strings::join("\n\n", bodies));

  return result;
}

// Verifies the functionality of the `CombinedAuthenticator`.
//
// Note: This test relies on the order of invocation of the installed
// authenticators. If the `CombinedAuthenticator` is changed in the future to
// call them in a different order, this test must be udpated.
TEST(CombinedAuthenticatorTest, MultipleAuthenticators)
{
  // Create two mock HTTP authenticators to install.
  MockAuthenticator* basicAuthenticator = new MockAuthenticator("Basic");
  MockAuthenticator* bearerAuthenticator = new MockAuthenticator("Bearer");

  // Create a `CombinedAuthenticator` containing multiple authenticators.
  Owned<Authenticator> combinedAuthenticator(
      new CombinedAuthenticator(
          REALM,
          {
            Owned<Authenticator>(basicAuthenticator),
            Owned<Authenticator>(bearerAuthenticator)
          }
      ));

  Request request;
  request.headers.put(
      "Authorization",
      "Basic " + base64::encode("user:password"));

  // The first authenticator succeeds.
  {
    AuthenticationResult successfulResult;
    successfulResult.principal = Principal("user");

    EXPECT_CALL(*basicAuthenticator, authenticate(request))
      .WillOnce(Return(successfulResult));

    Future<AuthenticationResult> result =
      combinedAuthenticator->authenticate(request);
    AWAIT_EXPECT_EQ(successfulResult, result);
  }

  // The first authenticator fails but the second one succeeds.
  {
    AuthenticationResult successfulResult;
    successfulResult.principal = Principal("user");

    EXPECT_CALL(*basicAuthenticator, authenticate(request))
      .WillOnce(Return(createUnauthorized(*basicAuthenticator)));
    EXPECT_CALL(*bearerAuthenticator, authenticate(request))
      .WillOnce(Return(successfulResult));

    Future<AuthenticationResult> result =
      combinedAuthenticator->authenticate(request);
    AWAIT_EXPECT_EQ(successfulResult, result);
  }

  // Two Unauthorized results.
  {
    EXPECT_CALL(*basicAuthenticator, authenticate(request))
      .WillOnce(Return(createUnauthorized(*basicAuthenticator)));
    EXPECT_CALL(*bearerAuthenticator, authenticate(request))
      .WillOnce(Return(createUnauthorized(*bearerAuthenticator)));

    Future<AuthenticationResult> result =
      combinedAuthenticator->authenticate(request);
    AWAIT_EXPECT_EQ(
        createCombinedUnauthorized({*basicAuthenticator, *bearerAuthenticator}),
        result);
  }

  // One Unauthorized and one Forbidden result.
  {
    EXPECT_CALL(*basicAuthenticator, authenticate(request))
      .WillOnce(Return(createUnauthorized(*basicAuthenticator)));
    EXPECT_CALL(*bearerAuthenticator, authenticate(request))
      .WillOnce(Return(createForbidden(*bearerAuthenticator)));

    Future<AuthenticationResult> result =
      combinedAuthenticator->authenticate(request);
    AWAIT_EXPECT_EQ(createCombinedUnauthorized({*basicAuthenticator}), result);
  }

  // Two Forbidden results.
  {
    EXPECT_CALL(*basicAuthenticator, authenticate(request))
      .WillOnce(Return(createForbidden(*basicAuthenticator)));
    EXPECT_CALL(*bearerAuthenticator, authenticate(request))
      .WillOnce(Return(createForbidden(*bearerAuthenticator)));

    Future<AuthenticationResult> result =
      combinedAuthenticator->authenticate(request);
    AWAIT_EXPECT_EQ(
        createCombinedForbidden({*basicAuthenticator, *bearerAuthenticator}),
        result);
  }

  // Two empty results.
  {
    AuthenticationResult emptyResult;

    EXPECT_CALL(*basicAuthenticator, authenticate(request))
      .WillOnce(Return(emptyResult));
    EXPECT_CALL(*bearerAuthenticator, authenticate(request))
      .WillOnce(Return(emptyResult));

    Future<AuthenticationResult> result =
      combinedAuthenticator->authenticate(request);
    AWAIT_EXPECT_EQ(emptyResult, result);
  }

  // One empty and one Unauthorized result.
  {
    AuthenticationResult emptyResult;

    EXPECT_CALL(*basicAuthenticator, authenticate(request))
      .WillOnce(Return(emptyResult));
    EXPECT_CALL(*bearerAuthenticator, authenticate(request))
      .WillOnce(Return(createUnauthorized(*bearerAuthenticator)));

    Future<AuthenticationResult> result =
      combinedAuthenticator->authenticate(request);
    AWAIT_EXPECT_EQ(createCombinedUnauthorized({*bearerAuthenticator}), result);
  }

  // One empty and one successful result.
  {
    AuthenticationResult emptyResult;
    AuthenticationResult successfulResult;
    successfulResult.principal = Principal("user");

    EXPECT_CALL(*basicAuthenticator, authenticate(request))
      .WillOnce(Return(emptyResult));
    EXPECT_CALL(*bearerAuthenticator, authenticate(request))
      .WillOnce(Return(successfulResult));

    Future<AuthenticationResult> result =
      combinedAuthenticator->authenticate(request);
    AWAIT_EXPECT_EQ(successfulResult, result);
  }

  // Two failed futures.
  {
    Future<AuthenticationResult> failedResult(Failure("Failed result"));

    EXPECT_CALL(*basicAuthenticator, authenticate(request))
      .WillOnce(Return(failedResult));
    EXPECT_CALL(*bearerAuthenticator, authenticate(request))
      .WillOnce(Return(failedResult));

    Future<AuthenticationResult> result =
      combinedAuthenticator->authenticate(request);
    AWAIT_EXPECT_FAILED(result);
  }

  // One failed future and one Unauthorized result.
  {
    Future<AuthenticationResult> failedResult(Failure("Failed result"));

    EXPECT_CALL(*basicAuthenticator, authenticate(request))
      .WillOnce(Return(failedResult));
    EXPECT_CALL(*bearerAuthenticator, authenticate(request))
      .WillOnce(Return(createUnauthorized(*bearerAuthenticator)));

    Future<AuthenticationResult> result =
      combinedAuthenticator->authenticate(request);
    AWAIT_EXPECT_EQ(createCombinedUnauthorized({*bearerAuthenticator}), result);
  }

  // One failed future and one Forbidden result.
  {
    Future<AuthenticationResult> failedResult(Failure("Failed result"));

    EXPECT_CALL(*basicAuthenticator, authenticate(request))
      .WillOnce(Return(failedResult));
    EXPECT_CALL(*bearerAuthenticator, authenticate(request))
      .WillOnce(Return(createForbidden(*bearerAuthenticator)));

    Future<AuthenticationResult> result =
      combinedAuthenticator->authenticate(request);
    AWAIT_EXPECT_EQ(createCombinedForbidden({*bearerAuthenticator}), result);
  }

  // One failed future and one successful result.
  {
    Future<AuthenticationResult> failedResult(Failure("Failed result"));
    AuthenticationResult successfulResult;
    successfulResult.principal = Principal("user");

    EXPECT_CALL(*basicAuthenticator, authenticate(request))
      .WillOnce(Return(failedResult));
    EXPECT_CALL(*bearerAuthenticator, authenticate(request))
      .WillOnce(Return(successfulResult));

    Future<AuthenticationResult> result =
      combinedAuthenticator->authenticate(request);
    AWAIT_EXPECT_EQ(successfulResult, result);
  }
}

} // namespace tests {
} // namespace internal {
} // namespace mesos {
<|endoftext|>