<commit_before>/// Copyright 2018 Pinterest Inc.
///
/// 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.

//
// @author angxu (angxu@pinterest.com)
//

#include <sys/socket.h>
#include <csignal>
#include <chrono>
#include <string>

#include "folly/Baton.h"
#include "folly/io/async/AsyncSignalHandler.h"
#include "gtest/gtest.h"

#include "common/graceful_shutdown_handler.h"
#include "common/timer.h"
#include "common/tests/thrift/gen-cpp2/DummyService.h"
#include "common/thrift_client_pool.h"

using apache::thrift::HandlerCallback;
using apache::thrift::RpcOptions;
using apache::thrift::transport::TTransportException;
using apache::thrift::TApplicationException;
using common::ThriftClientPool;
using dummy_service::thrift::DummyServiceSvIf;
using dummy_service::thrift::DummyServiceAsyncClient;
using folly::AsyncSignalHandler;
using folly::AsyncSocket;
using folly::EventBaseManager;
using folly::makeFuture;
using folly::Unit;
using std::chrono::milliseconds;
using std::chrono::seconds;

namespace common {

struct LatchServiceHandler : public DummyServiceSvIf {
  void async_tm_ping(
      std::unique_ptr<apache::thrift::HandlerCallback<void>> callback)
    override {
    callback->done();
  }

  void async_tm_getSomething(
      std::unique_ptr<apache::thrift::HandlerCallback<int64_t>> callback,
      int64_t input) override {
    baton_.wait();
    callback->result(input);
  }

  folly::Baton<> baton_;
};

class GracefulShutdownTest : public ::testing::Test {
 protected:
  void SetUp() override {
    handler_ = std::make_shared<LatchServiceHandler>();
    server_ = std::make_shared<apache::thrift::ThriftServer>();
    server_->setUseClientTimeout(true);
    server_->setPort(port_);
    server_->setInterface(handler_);
  }

  std::string host_ = "127.0.0.1";
  int port_ = 59090;
  std::shared_ptr<LatchServiceHandler> handler_;
  std::shared_ptr<apache::thrift::ThriftServer> server_;
};

TEST_F(GracefulShutdownTest, OneOutstandingRequestTest) {
  // starts server
  std::thread server_thread([this] {
      GracefulShutdownHandler gracefulShutdown(server_);
      gracefulShutdown.RegisterShutdownSignal(SIGUSR1);
      server_->serve();
  });
  sleep(1);

  ThriftClientPool<DummyServiceAsyncClient> client_pool;
  auto client = client_pool.getClient(server_->getAddress());

  RpcOptions options;
  options.setTimeout(seconds(5));
  // send a request before shutdown
  auto successful_result = client->future_getSomething(options, 123);
  sleep(1);
  // signal shutdown
  std::raise(SIGUSR1);
  sleep(1);
  // now allow the request to finish
  handler_->baton_.post();
  EXPECT_EQ(successful_result.get(), 123);

  // make sure server is shut down
  server_thread.join();

  // send a request after shutdown
  auto failure_result = client->future_getSomething(options, 456);
  EXPECT_THROW(failure_result.get(), TTransportException);
}

TEST_F(GracefulShutdownTest, TwoOutstandingRequestTest) {
  // starts server
  std::thread server_thread([this] {
      GracefulShutdownHandler gracefulShutdown(server_);
      gracefulShutdown.RegisterShutdownSignal(SIGUSR1);
      server_->setNPoolThreads(1);
      server_->serve();
  });
  sleep(1);

  ThriftClientPool<DummyServiceAsyncClient> client_pool;
  auto client = client_pool.getClient(server_->getAddress());

  RpcOptions options;
  options.setTimeout(seconds(5));
  // send a request before shutdown
  auto successful_result = client->future_getSomething(options, 123);
  auto successful_result2 = client->future_getSomething(options, 456);
  sleep(1);
  // signal shutdown
  std::raise(SIGUSR1);
  sleep(1);
  // now allow the request to finish
  handler_->baton_.post();
  EXPECT_EQ(successful_result.get(), 123);
  EXPECT_EQ(successful_result2.get(), 456);

  // make sure server is shut down
  server_thread.join();
}

TEST_F(GracefulShutdownTest, NewRequestAfterPostShutdownTest) {
  // starts server
  std::thread server_thread([this] {
      GracefulShutdownHandler gracefulShutdown(server_);
      gracefulShutdown.RegisterShutdownSignal(SIGUSR1);
      server_->serve();
  });
  sleep(1);

  ThriftClientPool<DummyServiceAsyncClient> client_pool;
  auto client = client_pool.getClient(server_->getAddress());
  RpcOptions options;
  options.setTimeout(seconds(5));
  auto successful_result = client->future_getSomething(options, 123);
  sleep(1);
  // signal shutdown
  std::raise(SIGUSR1);
  sleep(1);
  EXPECT_THROW(client->future_getSomething(options, 456).get(),
               std::exception);

  handler_->baton_.post();
  EXPECT_EQ(successful_result.get(), 123);
  server_thread.join();
}

TEST_F(GracefulShutdownTest, NewConnectionAfterPostShutdownTest) {
  // starts server
  std::thread server_thread([this] {
      GracefulShutdownHandler gracefulShutdown(server_);
      gracefulShutdown.RegisterShutdownSignal(SIGUSR1);
      server_->serve();
  });
  sleep(1);

  ThriftClientPool<DummyServiceAsyncClient> client_pool;
  auto client = client_pool.getClient(server_->getAddress());
  RpcOptions options;
  options.setTimeout(seconds(5));
  auto successful_result = client->future_getSomething(options, 123);

  // signal shutdown
  std::raise(SIGUSR1);
  sleep(1);

  struct ConnCallback : public AsyncSocket::ConnectCallback {
    explicit ConnCallback()
      : exception_(folly::AsyncSocketException::UNKNOWN, "none") {}
    void connectSuccess() noexcept override {}
    void connectErr(const folly::AsyncSocketException& ex) noexcept override {
      exception_ = ex;
    }
    folly::AsyncSocketException exception_;
  };
  folly::EventBase evb;
  ConnCallback cb;
  auto socket = AsyncSocket::newSocket(&evb);
  socket->connect(&cb, server_->getAddress(), 30);
  evb.loop();
  EXPECT_EQ(cb.exception_.getType(), folly::AsyncSocketException::NOT_OPEN);

  handler_->baton_.post();
  EXPECT_EQ(successful_result.get(), 123);
  server_thread.join();
}

}  // namespace common

int main(int argc, char** argv) {
  FLAGS_logtostderr = 1;
  google::InitGoogleLogging(argv[0]);
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
<commit_msg>[common] ensure the request is sent out before the signal<commit_after>/// Copyright 2018 Pinterest Inc.
///
/// 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.

//
// @author angxu (angxu@pinterest.com)
//

#include <sys/socket.h>
#include <csignal>
#include <chrono>
#include <string>

#include "folly/Baton.h"
#include "folly/io/async/AsyncSignalHandler.h"
#include "gtest/gtest.h"

#include "common/graceful_shutdown_handler.h"
#include "common/timer.h"
#include "common/tests/thrift/gen-cpp2/DummyService.h"
#include "common/thrift_client_pool.h"

using apache::thrift::HandlerCallback;
using apache::thrift::RpcOptions;
using apache::thrift::transport::TTransportException;
using apache::thrift::TApplicationException;
using common::ThriftClientPool;
using dummy_service::thrift::DummyServiceSvIf;
using dummy_service::thrift::DummyServiceAsyncClient;
using folly::AsyncSignalHandler;
using folly::AsyncSocket;
using folly::EventBaseManager;
using folly::makeFuture;
using folly::Unit;
using std::chrono::milliseconds;
using std::chrono::seconds;

namespace common {

struct LatchServiceHandler : public DummyServiceSvIf {
  void async_tm_ping(
      std::unique_ptr<apache::thrift::HandlerCallback<void>> callback)
    override {
    callback->done();
  }

  void async_tm_getSomething(
      std::unique_ptr<apache::thrift::HandlerCallback<int64_t>> callback,
      int64_t input) override {
    baton_.wait();
    callback->result(input);
  }

  folly::Baton<> baton_;
};

class GracefulShutdownTest : public ::testing::Test {
 protected:
  void SetUp() override {
    handler_ = std::make_shared<LatchServiceHandler>();
    server_ = std::make_shared<apache::thrift::ThriftServer>();
    server_->setUseClientTimeout(true);
    server_->setPort(port_);
    server_->setInterface(handler_);
  }

  std::string host_ = "127.0.0.1";
  int port_ = 59090;
  std::shared_ptr<LatchServiceHandler> handler_;
  std::shared_ptr<apache::thrift::ThriftServer> server_;
};

TEST_F(GracefulShutdownTest, OneOutstandingRequestTest) {
  // starts server
  std::thread server_thread([this] {
      GracefulShutdownHandler gracefulShutdown(server_);
      gracefulShutdown.RegisterShutdownSignal(SIGUSR1);
      server_->serve();
  });
  sleep(1);

  ThriftClientPool<DummyServiceAsyncClient> client_pool;
  auto client = client_pool.getClient(server_->getAddress());

  RpcOptions options;
  options.setTimeout(seconds(5));
  // send a request before shutdown
  auto successful_result = client->future_getSomething(options, 123);
  sleep(1);
  // signal shutdown
  std::raise(SIGUSR1);
  sleep(1);
  // now allow the request to finish
  handler_->baton_.post();
  EXPECT_EQ(successful_result.get(), 123);

  // make sure server is shut down
  server_thread.join();

  // send a request after shutdown
  auto failure_result = client->future_getSomething(options, 456);
  EXPECT_THROW(failure_result.get(), TTransportException);
}

TEST_F(GracefulShutdownTest, TwoOutstandingRequestTest) {
  // starts server
  std::thread server_thread([this] {
      GracefulShutdownHandler gracefulShutdown(server_);
      gracefulShutdown.RegisterShutdownSignal(SIGUSR1);
      server_->setNPoolThreads(1);
      server_->serve();
  });
  sleep(1);

  ThriftClientPool<DummyServiceAsyncClient> client_pool;
  auto client = client_pool.getClient(server_->getAddress());

  RpcOptions options;
  options.setTimeout(seconds(5));
  // send a request before shutdown
  auto successful_result = client->future_getSomething(options, 123);
  auto successful_result2 = client->future_getSomething(options, 456);
  sleep(1);
  // signal shutdown
  std::raise(SIGUSR1);
  sleep(1);
  // now allow the request to finish
  handler_->baton_.post();
  EXPECT_EQ(successful_result.get(), 123);
  EXPECT_EQ(successful_result2.get(), 456);

  // make sure server is shut down
  server_thread.join();
}

TEST_F(GracefulShutdownTest, NewRequestAfterPostShutdownTest) {
  // starts server
  std::thread server_thread([this] {
      GracefulShutdownHandler gracefulShutdown(server_);
      gracefulShutdown.RegisterShutdownSignal(SIGUSR1);
      server_->serve();
  });
  sleep(1);

  ThriftClientPool<DummyServiceAsyncClient> client_pool;
  auto client = client_pool.getClient(server_->getAddress());
  RpcOptions options;
  options.setTimeout(seconds(5));
  auto successful_result = client->future_getSomething(options, 123);
  sleep(1);
  // signal shutdown
  std::raise(SIGUSR1);
  sleep(1);
  EXPECT_THROW(client->future_getSomething(options, 456).get(),
               std::exception);

  handler_->baton_.post();
  EXPECT_EQ(successful_result.get(), 123);
  server_thread.join();
}

TEST_F(GracefulShutdownTest, NewConnectionAfterPostShutdownTest) {
  // starts server
  std::thread server_thread([this] {
      GracefulShutdownHandler gracefulShutdown(server_);
      gracefulShutdown.RegisterShutdownSignal(SIGUSR1);
      server_->serve();
  });
  sleep(1);

  ThriftClientPool<DummyServiceAsyncClient> client_pool;
  auto client = client_pool.getClient(server_->getAddress());
  RpcOptions options;
  options.setTimeout(seconds(5));
  auto successful_result = client->future_getSomething(options, 123);
  sleep(1);
  // signal shutdown
  std::raise(SIGUSR1);
  sleep(1);

  struct ConnCallback : public AsyncSocket::ConnectCallback {
    explicit ConnCallback()
      : exception_(folly::AsyncSocketException::UNKNOWN, "none") {}
    void connectSuccess() noexcept override {}
    void connectErr(const folly::AsyncSocketException& ex) noexcept override {
      exception_ = ex;
    }
    folly::AsyncSocketException exception_;
  };
  folly::EventBase evb;
  ConnCallback cb;
  auto socket = AsyncSocket::newSocket(&evb);
  socket->connect(&cb, server_->getAddress(), 30);
  evb.loop();
  EXPECT_EQ(cb.exception_.getType(), folly::AsyncSocketException::NOT_OPEN);

  handler_->baton_.post();
  EXPECT_EQ(successful_result.get(), 123);
  server_thread.join();
}

}  // namespace common

int main(int argc, char** argv) {
  FLAGS_logtostderr = 1;
  google::InitGoogleLogging(argv[0]);
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: XMLTextListItemContext.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: rt $ $Date: 2004-07-13 08:37: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 _TOOLS_DEBUG_HXX
#include <tools/debug.hxx>
#endif

#ifndef _XMLOFF_XMLIMP_HXX
#include "xmlimp.hxx"
#endif
#ifndef _XMLOFF_NMSPMAP_HXX
#include "nmspmap.hxx"
#endif
#ifndef _XMLOFF_XMLNMSPE_HXX
#include "xmlnmspe.hxx"
#endif
#ifndef _XMLOFF_XMLTOKEN_HXX
#include "xmltoken.hxx"
#endif
#ifndef _XMLOFF_TXTPARAI_HXX
#include "txtparai.hxx"
#endif
#ifndef _XMLTEXTLISTBLOCKCONTEXT_HXX
#include "XMLTextListBlockContext.hxx"
#endif
#ifndef _XMLOFF_TXTIMP_HXX
#include "txtimp.hxx"
#endif

#ifndef _XMLTEXTLISTITEMCONTEXT_HXX
#include "XMLTextListItemContext.hxx"
#endif

using namespace ::rtl;
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::xmloff::token;

TYPEINIT1( XMLTextListItemContext, SvXMLImportContext );

XMLTextListItemContext::XMLTextListItemContext(
        SvXMLImport& rImport,
        XMLTextImportHelper& rTxtImp, sal_uInt16 nPrfx,
        const OUString& rLName,
        const Reference< xml::sax::XAttributeList > & xAttrList,
        sal_Bool bIsHeader ) :
    SvXMLImportContext( rImport, nPrfx, rLName ),
    rTxtImport( rTxtImp ),
    nStartValue( -1 )
{
    sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
    for( sal_Int16 i=0; i < nAttrCount; i++ )
    {
        const OUString& rAttrName = xAttrList->getNameByIndex( i );
        const OUString& rValue = xAttrList->getValueByIndex( i );

        OUString aLocalName;
        sal_uInt16 nPrefix =
            GetImport().GetNamespaceMap().GetKeyByAttrName( rAttrName,
                                                            &aLocalName );
        if( !bIsHeader && XML_NAMESPACE_TEXT == nPrefix &&
            IsXMLToken( aLocalName, XML_START_VALUE ) )
        {
            sal_Int32 nTmp = rValue.toInt32();
            if( nTmp >= 0 && nTmp <= SHRT_MAX )
                nStartValue = (sal_Int16)nTmp;
        }
    }

    DBG_ASSERT( !rTxtImport.GetListItem(),
        "SwXMLListItemContext::SwXMLListItemContext: list item is existing" );

    // If this is a <text:list-item> element, then remember it as a sign
    // that a bullet has to be generated.
    if( !bIsHeader )
        rTxtImport.SetListItem( this );
}

XMLTextListItemContext::~XMLTextListItemContext()
{
}

void XMLTextListItemContext::EndElement()
{
    // finish current list item
    rTxtImport.SetListItem( 0 );
}

SvXMLImportContext *XMLTextListItemContext::CreateChildContext(
        sal_uInt16 nPrefix,
        const OUString& rLocalName,
        const Reference< xml::sax::XAttributeList > & xAttrList )
{
    SvXMLImportContext *pContext = 0;

    const SvXMLTokenMap& rTokenMap = rTxtImport.GetTextElemTokenMap();
    sal_Bool bHeading = sal_False;
    switch( rTokenMap.Get( nPrefix, rLocalName ) )
    {
    case XML_TOK_TEXT_H:
        bHeading = sal_True;
    case XML_TOK_TEXT_P:
        pContext = new XMLParaContext( GetImport(),
                                       nPrefix, rLocalName,
                                       xAttrList, bHeading );
        if (rTxtImport.IsProgress())
            GetImport().GetProgressBarHelper()->Increment();

        break;
    case XML_TOK_TEXT_LIST:
        pContext = new XMLTextListBlockContext( GetImport(), rTxtImport,
                                            nPrefix, rLocalName,
                                            xAttrList );
        break;
    }

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

    return pContext;
}

<commit_msg>INTEGRATION: CWS ooo19126 (1.5.298); FILE MERGED 2005/09/05 14:40:03 rt 1.5.298.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: XMLTextListItemContext.cxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 15:22:52 $
 *
 *  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 _TOOLS_DEBUG_HXX
#include <tools/debug.hxx>
#endif

#ifndef _XMLOFF_XMLIMP_HXX
#include "xmlimp.hxx"
#endif
#ifndef _XMLOFF_NMSPMAP_HXX
#include "nmspmap.hxx"
#endif
#ifndef _XMLOFF_XMLNMSPE_HXX
#include "xmlnmspe.hxx"
#endif
#ifndef _XMLOFF_XMLTOKEN_HXX
#include "xmltoken.hxx"
#endif
#ifndef _XMLOFF_TXTPARAI_HXX
#include "txtparai.hxx"
#endif
#ifndef _XMLTEXTLISTBLOCKCONTEXT_HXX
#include "XMLTextListBlockContext.hxx"
#endif
#ifndef _XMLOFF_TXTIMP_HXX
#include "txtimp.hxx"
#endif

#ifndef _XMLTEXTLISTITEMCONTEXT_HXX
#include "XMLTextListItemContext.hxx"
#endif

using namespace ::rtl;
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::xmloff::token;

TYPEINIT1( XMLTextListItemContext, SvXMLImportContext );

XMLTextListItemContext::XMLTextListItemContext(
        SvXMLImport& rImport,
        XMLTextImportHelper& rTxtImp, sal_uInt16 nPrfx,
        const OUString& rLName,
        const Reference< xml::sax::XAttributeList > & xAttrList,
        sal_Bool bIsHeader ) :
    SvXMLImportContext( rImport, nPrfx, rLName ),
    rTxtImport( rTxtImp ),
    nStartValue( -1 )
{
    sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
    for( sal_Int16 i=0; i < nAttrCount; i++ )
    {
        const OUString& rAttrName = xAttrList->getNameByIndex( i );
        const OUString& rValue = xAttrList->getValueByIndex( i );

        OUString aLocalName;
        sal_uInt16 nPrefix =
            GetImport().GetNamespaceMap().GetKeyByAttrName( rAttrName,
                                                            &aLocalName );
        if( !bIsHeader && XML_NAMESPACE_TEXT == nPrefix &&
            IsXMLToken( aLocalName, XML_START_VALUE ) )
        {
            sal_Int32 nTmp = rValue.toInt32();
            if( nTmp >= 0 && nTmp <= SHRT_MAX )
                nStartValue = (sal_Int16)nTmp;
        }
    }

    DBG_ASSERT( !rTxtImport.GetListItem(),
        "SwXMLListItemContext::SwXMLListItemContext: list item is existing" );

    // If this is a <text:list-item> element, then remember it as a sign
    // that a bullet has to be generated.
    if( !bIsHeader )
        rTxtImport.SetListItem( this );
}

XMLTextListItemContext::~XMLTextListItemContext()
{
}

void XMLTextListItemContext::EndElement()
{
    // finish current list item
    rTxtImport.SetListItem( 0 );
}

SvXMLImportContext *XMLTextListItemContext::CreateChildContext(
        sal_uInt16 nPrefix,
        const OUString& rLocalName,
        const Reference< xml::sax::XAttributeList > & xAttrList )
{
    SvXMLImportContext *pContext = 0;

    const SvXMLTokenMap& rTokenMap = rTxtImport.GetTextElemTokenMap();
    sal_Bool bHeading = sal_False;
    switch( rTokenMap.Get( nPrefix, rLocalName ) )
    {
    case XML_TOK_TEXT_H:
        bHeading = sal_True;
    case XML_TOK_TEXT_P:
        pContext = new XMLParaContext( GetImport(),
                                       nPrefix, rLocalName,
                                       xAttrList, bHeading );
        if (rTxtImport.IsProgress())
            GetImport().GetProgressBarHelper()->Increment();

        break;
    case XML_TOK_TEXT_LIST:
        pContext = new XMLTextListBlockContext( GetImport(), rTxtImport,
                                            nPrefix, rLocalName,
                                            xAttrList );
        break;
    }

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

    return pContext;
}

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: rscall.cxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: pl $ $Date: 2001-10-10 11:51:25 $
 *
 *  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): _______________________________________
 *
 *
 ************************************************************************/
/****************** I N C L U D E S **************************************/

// C and C++ Includes.
#include <stdlib.h>
#include <stdio.h>

// Programmabhaengige Includes.
#ifndef _RSCALL_H
#include <rscall.h>
#endif
#ifndef _RSCKEY_HXX
#include <rsckey.hxx>
#endif
#ifndef _RSCHASH_HXX
#include <rschash.hxx>
#endif

USHORT  nRsc_XYMAPMODEId;
USHORT  nRsc_WHMAPMODEId;
USHORT  nRsc_X;
USHORT  nRsc_Y;
USHORT  nRsc_WIDTH;
USHORT  nRsc_HEIGHT;
USHORT  nRsc_DELTALANG;
USHORT  nRsc_DELTASYSTEM;
USHORT  nRsc_EXTRADATA;

void InitRscCompiler()
{
    pHS              = new HashString( 3271 );

    pStdParType      = new ByteString( "( const ResId & rResId, BOOL" );
    pStdPar1         = new ByteString( '(' );
    pStdPar2         = new ByteString( '(' );

    pWinParType      = new ByteString( "( Window * pParent, const ResId & rResId, BOOL" );
    pWinPar1         = new ByteString( "( pParent," );
    pWinPar2         = new ByteString( "( this," );
    nRefDeep         = 10;
    nRsc_XYMAPMODEId = HASH_NONAME;
    nRsc_WHMAPMODEId = HASH_NONAME;
};

<commit_msg>INTEGRATION: CWS res32bit (1.2.152); FILE MERGED 2004/10/27 17:50:55 pl 1.2.152.2: minor updates 2004/10/22 13:54:35 pl 1.2.152.1: #i34513# free rsc of 32 bit constraints<commit_after>/*************************************************************************
 *
 *  $RCSfile: rscall.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: obo $ $Date: 2005-01-03 17:27:50 $
 *
 *  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): _______________________________________
 *
 *
 ************************************************************************/
/****************** I N C L U D E S **************************************/

// C and C++ Includes.
#include <stdlib.h>
#include <stdio.h>

// Programmabhaengige Includes.
#ifndef _RSCALL_H
#include <rscall.h>
#endif
#ifndef _RSCKEY_HXX
#include <rsckey.hxx>
#endif

Atom    nRsc_XYMAPMODEId = InvalidAtom;
Atom    nRsc_WHMAPMODEId = InvalidAtom;
Atom    nRsc_X = InvalidAtom;
Atom    nRsc_Y = InvalidAtom;
Atom    nRsc_WIDTH = InvalidAtom;
Atom    nRsc_HEIGHT = InvalidAtom;
Atom    nRsc_DELTALANG = InvalidAtom;
Atom    nRsc_DELTASYSTEM = InvalidAtom;
Atom    nRsc_EXTRADATA = InvalidAtom;

void InitRscCompiler()
{
    pStdParType      = new ByteString( "( const ResId & rResId, BOOL" );
    pStdPar1         = new ByteString( '(' );
    pStdPar2         = new ByteString( '(' );

    pWinParType      = new ByteString( "( Window * pParent, const ResId & rResId, BOOL" );
    pWinPar1         = new ByteString( "( pParent," );
    pWinPar2         = new ByteString( "( this," );
    nRefDeep         = 10;
    nRsc_XYMAPMODEId = InvalidAtom;
    nRsc_WHMAPMODEId = InvalidAtom;
    pHS = new AtomContainer();
};

<|endoftext|>


<commit_before>/**************************************************************************
 * Copyright(c) 2009-2012, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/
/* $Id$ */

///////////////////////////////////////////////////////////////////
//                                                               //
// Class to store information for PID with ITS                   //
// and truncated mean computation methods                        //
// Origin: F.Prino, Torino, prino@to.infn.it                     //
//                                                               //
///////////////////////////////////////////////////////////////////

#include "AliITSPidParams.h"
#include "AliITSdEdxSamples.h"
#include "AliLog.h"
#include <TMath.h>

ClassImp(AliITSdEdxSamples)

//______________________________________________________________________
AliITSdEdxSamples::AliITSdEdxSamples():TObject(),
  fNSamples(0),
  fP(0.),
  fParticleSpecie(0)
{
  // Default constructor

  for(Int_t i=0; i<fgkMaxSamples; i++) fdEdxSamples[i]=0.;
}

//______________________________________________________________________
AliITSdEdxSamples::AliITSdEdxSamples(Int_t nSamples,Double_t* samples, Double_t mom, Int_t specie) :
  TObject(),
  fNSamples(nSamples),
  fP(mom),
  fParticleSpecie(specie)
{
  // Standard constructor

  SetSamples(nSamples,samples);
}
//______________________________________________________________________
void AliITSdEdxSamples::SetSamples(Int_t nSamples, Double_t* samples){
  // Set the samples

  if(nSamples>fgkMaxSamples){
    AliWarning(Form("Too many dE/dx samples,only first %d will be used",fgkMaxSamples));
    fNSamples=fgkMaxSamples;
  }else{
    fNSamples=nSamples;
  }
  for(Int_t i=0; i<fNSamples; i++) fdEdxSamples[i]=samples[i];
  for(Int_t i=fNSamples; i<fgkMaxSamples; i++) fdEdxSamples[i]=0.;
  return;
}
//______________________________________________________________________
void AliITSdEdxSamples::SetSamplesAndMomenta(Int_t nSamples, Double_t* samples, Double_t* mom){
  // Set the samples
  SetSamples(nSamples,samples);
  for(Int_t i=0; i<fNSamples; i++) fPAtSample[i]=mom[i];
  for(Int_t i=fNSamples; i<fgkMaxSamples; i++) fPAtSample[i]=0.;
  return;
}
//______________________________________________________________________
Double_t AliITSdEdxSamples::GetTruncatedMean(Double_t frac, Double_t mindedx) const {
  // compute truncated mean

  Int_t nc=0;
  Double_t dedx[fgkMaxSamples];
  for (Int_t il=0; il<fNSamples; il++) { // count good (>0) dE/dx values
    if(fdEdxSamples[il]>mindedx){
      dedx[nc]= fdEdxSamples[il];
      nc++;
    }
  }
  if(nc<1) return 0.;

  Int_t swap; // sort in ascending order
  do {
    swap=0;
    for (Int_t i=0; i<nc-1; i++) {
      if (dedx[i]<=dedx[i+1]) continue;
      Double_t tmp=dedx[i];
      dedx[i]=dedx[i+1];
      dedx[i+1]=tmp;
      swap++;
    }
  } while (swap);

  Double_t sumamp=0,sumweight=0;
  Double_t weight[fgkMaxSamples];
  for(Int_t iw=0; iw<fgkMaxSamples; iw++) weight[iw]=0.;
  Int_t lastUsed=(Int_t)(frac*nc+0.00001);
  if(lastUsed==0) lastUsed=1;
  if(lastUsed>fgkMaxSamples) lastUsed=fgkMaxSamples;
  for(Int_t iw=0; iw<lastUsed; iw++) weight[iw]=1.;
  if((frac*nc-lastUsed)>0.4 && lastUsed<fgkMaxSamples) weight[lastUsed]=0.5;
  for (Int_t i=0; i<nc; i++) {
    AliDebug(5,Form("dE/dx %f   weight %f",dedx[i],weight[i]));
    sumamp+= dedx[i]*weight[i];
    sumweight+=weight[i];
  }
  if(sumweight>0.) return sumamp/sumweight;
  else return 0.;

}
//______________________________________________________________________
Double_t AliITSdEdxSamples::GetWeightedMean(Double_t mindedx) const {
  // compute generalized mean with k=-2 (used by CMS)

  Int_t nc=0;
  Double_t dedx[fgkMaxSamples];
  for (Int_t il=0; il<fNSamples; il++) { // count good (>0) dE/dx values
    if(fdEdxSamples[il]>mindedx){
      dedx[nc]= fdEdxSamples[il];
      nc++;
    }
  }
  if(nc<1) return 0.;

  Double_t weiSum = 0.;
  for (Int_t i=0; i<nc; i++) {
    weiSum+=TMath::Power(dedx[i],-2);
  }
  Double_t wMean=0.;
  if(weiSum>0.) wMean= TMath::Power(weiSum/nc,-0.5);
  return wMean;

}
//______________________________________________________________________
void  AliITSdEdxSamples::GetConditionalProbabilities(AliITSPidParams* pars, Double_t condprob[AliPID::kSPECIES], Double_t mindedx) const {
  // compute conditional probablilities
  const Int_t nPart = 3;
  Double_t itsProb[nPart] = {1,1,1}; // p, K, pi

  for(Int_t iS=0; iS<fNSamples; iS++){
    Int_t iLayer=iS+3; // to match with present ITS
    if(iLayer>6) iLayer=6; // all extra points are treated as SSD
    if(fdEdxSamples[iS]<mindedx) continue;
    Float_t dedx = fdEdxSamples[iS];
    Float_t layProb = pars->GetLandauGausNorm(dedx,AliPID::kProton,fP,iLayer);
    itsProb[0] *= layProb;

    layProb = pars->GetLandauGausNorm(dedx,AliPID::kKaon,fP,iLayer);
    if (fP < 0.16) layProb=0.00001;
    itsProb[1] *= layProb;

    layProb = pars->GetLandauGausNorm(dedx,AliPID::kPion,fP,iLayer);
    itsProb[2] *= layProb;
  }

  // Normalise probabilities
  Double_t sumProb = 0;
  for (Int_t iPart = 0; iPart < nPart; iPart++) {
    sumProb += itsProb[iPart];
  }
  sumProb += 2*itsProb[2]; // muon and electron cannot be distinguished from pions

  for (Int_t iPart = 0; iPart < nPart; iPart++) {
    itsProb[iPart]/=sumProb;
  }

  condprob[AliPID::kElectron] = itsProb[2];
  condprob[AliPID::kMuon] = itsProb[2];
  condprob[AliPID::kPion] = itsProb[2];
  condprob[AliPID::kKaon] = itsProb[1];
  condprob[AliPID::kProton] = itsProb[0];
  return;

}
<commit_msg>Fix for Coverity warning 16208<commit_after>/**************************************************************************
 * Copyright(c) 2009-2012, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/
/* $Id$ */

///////////////////////////////////////////////////////////////////
//                                                               //
// Class to store information for PID with ITS                   //
// and truncated mean computation methods                        //
// Origin: F.Prino, Torino, prino@to.infn.it                     //
//                                                               //
///////////////////////////////////////////////////////////////////

#include "AliITSPidParams.h"
#include "AliITSdEdxSamples.h"
#include "AliLog.h"
#include <TMath.h>

ClassImp(AliITSdEdxSamples)

//______________________________________________________________________
AliITSdEdxSamples::AliITSdEdxSamples():TObject(),
  fNSamples(0),
  fP(0.),
  fParticleSpecie(0)
{
  // Default constructor

  for(Int_t i=0; i<fgkMaxSamples; i++) {
    fdEdxSamples[i]=0.;
    fPAtSample[i]=0.;
  }
}

//______________________________________________________________________
AliITSdEdxSamples::AliITSdEdxSamples(Int_t nSamples,Double_t* samples, Double_t mom, Int_t specie) :
  TObject(),
  fNSamples(nSamples),
  fP(mom),
  fParticleSpecie(specie)
{
  // Standard constructor
  for(Int_t i=0; i<fgkMaxSamples; i++)fPAtSample[i]=0.;
  SetSamples(nSamples,samples);
}
//______________________________________________________________________
void AliITSdEdxSamples::SetSamples(Int_t nSamples, Double_t* samples){
  // Set the samples

  if(nSamples>fgkMaxSamples){
    AliWarning(Form("Too many dE/dx samples,only first %d will be used",fgkMaxSamples));
    fNSamples=fgkMaxSamples;
  }else{
    fNSamples=nSamples;
  }
  for(Int_t i=0; i<fNSamples; i++) fdEdxSamples[i]=samples[i];
  for(Int_t i=fNSamples; i<fgkMaxSamples; i++) fdEdxSamples[i]=0.;
  return;
}
//______________________________________________________________________
void AliITSdEdxSamples::SetSamplesAndMomenta(Int_t nSamples, Double_t* samples, Double_t* mom){
  // Set the samples
  SetSamples(nSamples,samples);
  for(Int_t i=0; i<fNSamples; i++) fPAtSample[i]=mom[i];
  for(Int_t i=fNSamples; i<fgkMaxSamples; i++) fPAtSample[i]=0.;
  return;
}
//______________________________________________________________________
Double_t AliITSdEdxSamples::GetTruncatedMean(Double_t frac, Double_t mindedx) const {
  // compute truncated mean

  Int_t nc=0;
  Double_t dedx[fgkMaxSamples];
  for (Int_t il=0; il<fNSamples; il++) { // count good (>0) dE/dx values
    if(fdEdxSamples[il]>mindedx){
      dedx[nc]= fdEdxSamples[il];
      nc++;
    }
  }
  if(nc<1) return 0.;

  Int_t swap; // sort in ascending order
  do {
    swap=0;
    for (Int_t i=0; i<nc-1; i++) {
      if (dedx[i]<=dedx[i+1]) continue;
      Double_t tmp=dedx[i];
      dedx[i]=dedx[i+1];
      dedx[i+1]=tmp;
      swap++;
    }
  } while (swap);

  Double_t sumamp=0,sumweight=0;
  Double_t weight[fgkMaxSamples];
  for(Int_t iw=0; iw<fgkMaxSamples; iw++) weight[iw]=0.;
  Int_t lastUsed=(Int_t)(frac*nc+0.00001);
  if(lastUsed==0) lastUsed=1;
  if(lastUsed>fgkMaxSamples) lastUsed=fgkMaxSamples;
  for(Int_t iw=0; iw<lastUsed; iw++) weight[iw]=1.;
  if((frac*nc-lastUsed)>0.4 && lastUsed<fgkMaxSamples) weight[lastUsed]=0.5;
  for (Int_t i=0; i<nc; i++) {
    AliDebug(5,Form("dE/dx %f   weight %f",dedx[i],weight[i]));
    sumamp+= dedx[i]*weight[i];
    sumweight+=weight[i];
  }
  if(sumweight>0.) return sumamp/sumweight;
  else return 0.;

}
//______________________________________________________________________
Double_t AliITSdEdxSamples::GetWeightedMean(Double_t mindedx) const {
  // compute generalized mean with k=-2 (used by CMS)

  Int_t nc=0;
  Double_t dedx[fgkMaxSamples];
  for (Int_t il=0; il<fNSamples; il++) { // count good (>0) dE/dx values
    if(fdEdxSamples[il]>mindedx){
      dedx[nc]= fdEdxSamples[il];
      nc++;
    }
  }
  if(nc<1) return 0.;

  Double_t weiSum = 0.;
  for (Int_t i=0; i<nc; i++) {
    weiSum+=TMath::Power(dedx[i],-2);
  }
  Double_t wMean=0.;
  if(weiSum>0.) wMean= TMath::Power(weiSum/nc,-0.5);
  return wMean;

}
//______________________________________________________________________
void  AliITSdEdxSamples::GetConditionalProbabilities(AliITSPidParams* pars, Double_t condprob[AliPID::kSPECIES], Double_t mindedx) const {
  // compute conditional probablilities
  const Int_t nPart = 3;
  Double_t itsProb[nPart] = {1,1,1}; // p, K, pi

  for(Int_t iS=0; iS<fNSamples; iS++){
    Int_t iLayer=iS+3; // to match with present ITS
    if(iLayer>6) iLayer=6; // all extra points are treated as SSD
    if(fdEdxSamples[iS]<mindedx) continue;
    Float_t dedx = fdEdxSamples[iS];
    Float_t layProb = pars->GetLandauGausNorm(dedx,AliPID::kProton,fP,iLayer);
    itsProb[0] *= layProb;

    layProb = pars->GetLandauGausNorm(dedx,AliPID::kKaon,fP,iLayer);
    if (fP < 0.16) layProb=0.00001;
    itsProb[1] *= layProb;

    layProb = pars->GetLandauGausNorm(dedx,AliPID::kPion,fP,iLayer);
    itsProb[2] *= layProb;
  }

  // Normalise probabilities
  Double_t sumProb = 0;
  for (Int_t iPart = 0; iPart < nPart; iPart++) {
    sumProb += itsProb[iPart];
  }
  sumProb += 2*itsProb[2]; // muon and electron cannot be distinguished from pions

  for (Int_t iPart = 0; iPart < nPart; iPart++) {
    itsProb[iPart]/=sumProb;
  }

  condprob[AliPID::kElectron] = itsProb[2];
  condprob[AliPID::kMuon] = itsProb[2];
  condprob[AliPID::kPion] = itsProb[2];
  condprob[AliPID::kKaon] = itsProb[1];
  condprob[AliPID::kProton] = itsProb[0];
  return;

}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: xmltabe.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: mib $ $Date: 2001-05-07 07:50:54 $
 *
 *  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): _______________________________________
 *
 *
 ************************************************************************/

#include <tools/debug.hxx>

#ifndef _COM_SUN_STAR_STYLE_TABSTOP_HPP_
#include <com/sun/star/style/TabStop.hpp>
#endif
#ifndef _COM_SUN_STAR_STYLE_TABALIGN_HPP_
#include <com/sun/star/style/TabAlign.hpp>
#endif

#ifndef _RTL_USTRBUF_HXX_
#include <rtl/ustrbuf.hxx>
#endif

#ifndef _XMLOFF_NMSPMAP_HXX
#include "nmspmap.hxx"
#endif
#ifndef _XMLOFF_XMLNMSPE_HXX
#include "xmlnmspe.hxx"
#endif
#ifndef _XMLOFF_XMLKYWD_HXX
#include "xmlkywd.hxx"
#endif
#ifndef _XMLOFF_XMLITMAP_HXX
#include "xmlitmap.hxx"
#endif
#ifndef _XMLOFF_XMLUCONV_HXX
#include "xmluconv.hxx"
#endif
#ifndef _XMLOFF_XMLEXPIT_HXX
#include "xmlexpit.hxx"
#endif

#ifndef _XMLOFF_XMLTABE_HXX
#include "xmltabe.hxx"
#endif

using namespace ::rtl;
using namespace ::com::sun::star;

SvXMLEnumMapEntry psXML_tabstop_style[] =
{
    { "left", style::TabAlign_LEFT  },
    { "center", style::TabAlign_CENTER  },
    { "right", style::TabAlign_RIGHT    },
    { "char", style::TabAlign_DECIMAL   },
    { "default", style::TabAlign_DEFAULT  },    // ?????????????????????????????????????
    { 0,        0 }
};

void SvxXMLTabStopExport::exportTabStop( const ::com::sun::star::style::TabStop* pTabStop )
{
    CheckAttrList();

    // text:level
    OUStringBuffer sBuffer;

    // position attribute
    mrUnitConv.convertMeasure( sBuffer, pTabStop->Position );
    AddAttribute( XML_NAMESPACE_STYLE, sXML_position,
                  sBuffer.makeStringAndClear() );

    // type attribute
    if( style::TabAlign_LEFT != pTabStop->Alignment )
    {
        mrUnitConv.convertEnum( sBuffer, pTabStop->Alignment,
                                   psXML_tabstop_style );
        AddAttribute( XML_NAMESPACE_STYLE, sXML_type,
                      sBuffer.makeStringAndClear() );
    }

    // char
    if( style::TabAlign_DECIMAL == pTabStop->Alignment &&
        pTabStop->DecimalChar != 0 )
    {
        sBuffer.append( pTabStop->DecimalChar );
        AddAttribute( XML_NAMESPACE_STYLE, sXML_char,
                      sBuffer.makeStringAndClear() );
    }

    // leader-char
    if( ' ' != pTabStop->FillChar && 0 != pTabStop->FillChar )
    {
        sBuffer.append( pTabStop->FillChar );
        AddAttribute( XML_NAMESPACE_STYLE, sXML_leader_char,
                      sBuffer.makeStringAndClear() );
    }

    OUString sElem = GetQNameByKey( XML_NAMESPACE_STYLE, OUString::createFromAscii(sXML_tab_stop) );
    mxHandler->ignorableWhitespace( msWS );
    mxHandler->startElement( sElem, mxAttrList );
    ClearAttrList();
    mxHandler->ignorableWhitespace( msWS );
    mxHandler->endElement( sElem );
}

OUString SvxXMLTabStopExport::GetQNameByKey( sal_uInt16 nKey,
                                               const OUString& rLocalName ) const
{
    DBG_ASSERT( mpNamespaceMap,
                "SvxXMLTabStopExport::GetQNameByKey: namespace map is missing" );
    if( mpNamespaceMap )
        return mpNamespaceMap->GetQNameByKey( nKey, rLocalName );
    else
        return rLocalName;
}

void SvxXMLTabStopExport::ClearAttrList()
{
    mpAttrList->Clear();
}

#ifndef PRODUCT
void SvxXMLTabStopExport::CheckAttrList()
{
    DBG_ASSERT( !mpAttrList->getLength(),
                "SvxXMLTabStopExport::CheckAttrList: list is not empty" );
}
#endif

void SvxXMLTabStopExport::AddAttribute( sal_uInt16 nPrefixKey, const char *pName,
                                       const OUString& rValue )
{
    OUString sName( OUString::createFromAscii( pName ) );

    mpAttrList->AddAttribute( GetQNameByKey( nPrefixKey, sName ),
                             msCDATA, rValue );
}

SvxXMLTabStopExport::SvxXMLTabStopExport( const uno::Reference< ::com::sun::star::xml::sax::XDocumentHandler > & rHandler,
                                      const SvXMLUnitConverter& rUnitConverter )
:   msCDATA( OUString::createFromAscii( sXML_CDATA ) ),
    msWS( OUString::createFromAscii( sXML_WS ) ),
    mpNamespaceMap( 0 ),
    mrUnitConv( rUnitConverter ),
    mpAttrList( new SvXMLAttributeList )
{
    mxHandler = rHandler;
    mxAttrList = mpAttrList;
}

SvxXMLTabStopExport::~SvxXMLTabStopExport()
{
}

void SvxXMLTabStopExport::Export( const uno::Any& rAny,
                                  const SvXMLNamespaceMap& rNamespaceMap )
{
    mpNamespaceMap = &rNamespaceMap;

    CheckAttrList();

    uno::Sequence< ::com::sun::star::style::TabStop> aSeq;
    if(!(rAny >>= aSeq))
    {
        DBG_ERROR( "SvxXMLTabStopExport needs a Sequence ::com::sun::star::style::TabStop>" );
    }
    else
    {
        const ::com::sun::star::style::TabStop* pTabs = aSeq.getConstArray();
        const sal_uInt16 nTabs   = aSeq.getLength();

        // ignore default tab stop here
        //if( 1 == nTabs && style::TabAlign_DEFAULT == pTabs[0].Alignment )
        //  return;

        OUString sElem = GetQNameByKey( XML_NAMESPACE_STYLE,
                                       OUString::createFromAscii(sXML_tab_stops) );
        mxHandler->ignorableWhitespace( msWS );
        mxHandler->startElement( sElem, mxAttrList );
        ClearAttrList();

        for( sal_uInt16 nIndex = 0; nIndex < nTabs; nIndex++ )
        {
            DBG_ASSERT( style::TabAlign_DEFAULT == pTabs[nIndex].Alignment ||
                        nIndex == 0 ||
                        style::TabAlign_DEFAULT != pTabs[nIndex-1].Alignment,
                        "tab default distance unexpected" );
            if( style::TabAlign_DEFAULT != pTabs[nIndex].Alignment ||
                 0 == nIndex )
                exportTabStop( &(pTabs[nIndex]) );
        }

        mxHandler->ignorableWhitespace( msWS );
        mxHandler->endElement( sElem );
    }

    mpNamespaceMap = 0;
}

<commit_msg>#87041#: Don export default tab stops<commit_after>/*************************************************************************
 *
 *  $RCSfile: xmltabe.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: mib $ $Date: 2001-05-16 11:31:05 $
 *
 *  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): _______________________________________
 *
 *
 ************************************************************************/

#include <tools/debug.hxx>

#ifndef _COM_SUN_STAR_STYLE_TABSTOP_HPP_
#include <com/sun/star/style/TabStop.hpp>
#endif
#ifndef _COM_SUN_STAR_STYLE_TABALIGN_HPP_
#include <com/sun/star/style/TabAlign.hpp>
#endif

#ifndef _RTL_USTRBUF_HXX_
#include <rtl/ustrbuf.hxx>
#endif

#ifndef _XMLOFF_NMSPMAP_HXX
#include "nmspmap.hxx"
#endif
#ifndef _XMLOFF_XMLNMSPE_HXX
#include "xmlnmspe.hxx"
#endif
#ifndef _XMLOFF_XMLKYWD_HXX
#include "xmlkywd.hxx"
#endif
#ifndef _XMLOFF_XMLITMAP_HXX
#include "xmlitmap.hxx"
#endif
#ifndef _XMLOFF_XMLUCONV_HXX
#include "xmluconv.hxx"
#endif
#ifndef _XMLOFF_XMLEXPIT_HXX
#include "xmlexpit.hxx"
#endif

#ifndef _XMLOFF_XMLTABE_HXX
#include "xmltabe.hxx"
#endif

using namespace ::rtl;
using namespace ::com::sun::star;

SvXMLEnumMapEntry psXML_tabstop_style[] =
{
    { "left", style::TabAlign_LEFT  },
    { "center", style::TabAlign_CENTER  },
    { "right", style::TabAlign_RIGHT    },
    { "char", style::TabAlign_DECIMAL   },
    { "default", style::TabAlign_DEFAULT  },    // ?????????????????????????????????????
    { 0,        0 }
};

void SvxXMLTabStopExport::exportTabStop( const ::com::sun::star::style::TabStop* pTabStop )
{
    CheckAttrList();

    // text:level
    OUStringBuffer sBuffer;

    // position attribute
    mrUnitConv.convertMeasure( sBuffer, pTabStop->Position );
    AddAttribute( XML_NAMESPACE_STYLE, sXML_position,
                  sBuffer.makeStringAndClear() );

    // type attribute
    if( style::TabAlign_LEFT != pTabStop->Alignment )
    {
        mrUnitConv.convertEnum( sBuffer, pTabStop->Alignment,
                                   psXML_tabstop_style );
        AddAttribute( XML_NAMESPACE_STYLE, sXML_type,
                      sBuffer.makeStringAndClear() );
    }

    // char
    if( style::TabAlign_DECIMAL == pTabStop->Alignment &&
        pTabStop->DecimalChar != 0 )
    {
        sBuffer.append( pTabStop->DecimalChar );
        AddAttribute( XML_NAMESPACE_STYLE, sXML_char,
                      sBuffer.makeStringAndClear() );
    }

    // leader-char
    if( ' ' != pTabStop->FillChar && 0 != pTabStop->FillChar )
    {
        sBuffer.append( pTabStop->FillChar );
        AddAttribute( XML_NAMESPACE_STYLE, sXML_leader_char,
                      sBuffer.makeStringAndClear() );
    }

    OUString sElem = GetQNameByKey( XML_NAMESPACE_STYLE, OUString::createFromAscii(sXML_tab_stop) );
    mxHandler->ignorableWhitespace( msWS );
    mxHandler->startElement( sElem, mxAttrList );
    ClearAttrList();
    mxHandler->ignorableWhitespace( msWS );
    mxHandler->endElement( sElem );
}

OUString SvxXMLTabStopExport::GetQNameByKey( sal_uInt16 nKey,
                                               const OUString& rLocalName ) const
{
    DBG_ASSERT( mpNamespaceMap,
                "SvxXMLTabStopExport::GetQNameByKey: namespace map is missing" );
    if( mpNamespaceMap )
        return mpNamespaceMap->GetQNameByKey( nKey, rLocalName );
    else
        return rLocalName;
}

void SvxXMLTabStopExport::ClearAttrList()
{
    mpAttrList->Clear();
}

#ifndef PRODUCT
void SvxXMLTabStopExport::CheckAttrList()
{
    DBG_ASSERT( !mpAttrList->getLength(),
                "SvxXMLTabStopExport::CheckAttrList: list is not empty" );
}
#endif

void SvxXMLTabStopExport::AddAttribute( sal_uInt16 nPrefixKey, const char *pName,
                                       const OUString& rValue )
{
    OUString sName( OUString::createFromAscii( pName ) );

    mpAttrList->AddAttribute( GetQNameByKey( nPrefixKey, sName ),
                             msCDATA, rValue );
}

SvxXMLTabStopExport::SvxXMLTabStopExport( const uno::Reference< ::com::sun::star::xml::sax::XDocumentHandler > & rHandler,
                                      const SvXMLUnitConverter& rUnitConverter )
:   msCDATA( OUString::createFromAscii( sXML_CDATA ) ),
    msWS( OUString::createFromAscii( sXML_WS ) ),
    mpNamespaceMap( 0 ),
    mrUnitConv( rUnitConverter ),
    mpAttrList( new SvXMLAttributeList )
{
    mxHandler = rHandler;
    mxAttrList = mpAttrList;
}

SvxXMLTabStopExport::~SvxXMLTabStopExport()
{
}

void SvxXMLTabStopExport::Export( const uno::Any& rAny,
                                  const SvXMLNamespaceMap& rNamespaceMap )
{
    mpNamespaceMap = &rNamespaceMap;

    CheckAttrList();

    uno::Sequence< ::com::sun::star::style::TabStop> aSeq;
    if(!(rAny >>= aSeq))
    {
        DBG_ERROR( "SvxXMLTabStopExport needs a Sequence ::com::sun::star::style::TabStop>" );
    }
    else
    {
        const ::com::sun::star::style::TabStop* pTabs = aSeq.getConstArray();
        const sal_uInt16 nTabs   = aSeq.getLength();

        // ignore default tab stop here
        //if( 1 == nTabs && style::TabAlign_DEFAULT == pTabs[0].Alignment )
        //  return;

        OUString sElem = GetQNameByKey( XML_NAMESPACE_STYLE,
                                       OUString::createFromAscii(sXML_tab_stops) );
        mxHandler->ignorableWhitespace( msWS );
        mxHandler->startElement( sElem, mxAttrList );
        ClearAttrList();

        for( sal_uInt16 nIndex = 0; nIndex < nTabs; nIndex++ )
        {
            if( style::TabAlign_DEFAULT != pTabs[nIndex].Alignment )
                exportTabStop( &(pTabs[nIndex]) );
        }

        mxHandler->ignorableWhitespace( msWS );
        mxHandler->endElement( sElem );
    }

    mpNamespaceMap = 0;
}

<|endoftext|>


<commit_before>#include <time/time.hpp>
#include <packet.hpp>
#include <client.hpp>
#include <data_provider.hpp>
#include <thread_pool.hpp>
#include <cstddef>

namespace MCPP {

	class TimeSave {

		public:

			UInt64 Age;
			UInt64 Time;

	};

	#pragma GCC diagnostic push
	#pragma GCC diagnostic ignored "-Winvalid-offsetof"
	static_assert(
		offsetof(TimeSave,Time)==(offsetof(TimeSave,Age)+sizeof(UInt64)),
		"TimeSave layout incorrect"
	);
	#pragma GCC diagnostic pop

	static const String name("Time Module");
	static const Word priority=1;

	static const Word default_tick_length=50;
	static const Word day_length=24000;
	static const Word default_between_saves=5*60*20;	//	5 minutes
	static const bool default_offline_freeze=true;
	static const Word num_lunar_phases=8;
	static const Word threshold_percentage_default=10;	//	10%

	static const String time_key("time");
	static const String tick_length_key("tick_length");
	static const String offline_freeze_key("offline_freeze");
	static const String between_saves_key("maintenance_interval");
	static const String tick_error("Error while ticking");
	static const String tick_too_long("Tick took {0}% too long - Actual: {1}ms - Expected: {2}ms");
	static const String threshold_percentage_key("tick_threshold");
	static const Regex true_regex(
		"^\\s*(?:t(?:rue)?|y(?:es)?)\\s*$",
		RegexOptions().SetIgnoreCase()
	);
	static const Regex false_regex(
		"^\\s*(?:f(?:alse)?|n(?:o)?)\\s*$",
		RegexOptions().SetIgnoreCase()
	);

	static const String full_moon("Full");
	static const String waning_gibbous_moon("Waning Gibbous");
	static const String last_quarter_moon("Last Quarter");
	static const String waning_crescent_moon("Waning Crescent");
	static const String new_moon("New");
	static const String waxing_crescent_moon("Waxing Crescent");
	static const String first_quarter_moon("First Quarter");
	static const String waxing_gibbous_moon("Waxing Gibbous");

	const String & TimeModule::GetLunarPhase (LunarPhase phase) noexcept {

		switch (phase) {

			case LunarPhase::Full:
			default:return full_moon;

			case LunarPhase::WaningGibbous:return waning_gibbous_moon;

			case LunarPhase::LastQuarter:return last_quarter_moon;

			case LunarPhase::WaningCrescent:return waning_crescent_moon;

			case LunarPhase::New:return new_moon;

			case LunarPhase::WaxingCrescent:return waxing_crescent_moon;

			case LunarPhase::FirstQuarter:return first_quarter_moon;

			case LunarPhase::WaxingGibbous:return waxing_gibbous_moon;

		}

	}

	static const String day("Day");
	static const String dusk("Dusk");
	static const String dawn("Dawn");
	static const String night("Night");

	const String & TimeModule::GetTimeOfDay (TimeOfDay time_of_day) noexcept {

		switch (time_of_day) {

			case TimeOfDay::Day:
			default:return day;

			case TimeOfDay::Dusk:return dusk;

			case TimeOfDay::Night:return night;

			case TimeOfDay::Dawn:return dawn;

		}

	}

	TimeModule::TimeModule () noexcept {

		ticks=0;
		tick_time=0;
		executing=0;
		age=0;
		time=0;
		since=0;

	}

	const String & TimeModule::Name () const noexcept {

		return name;

	}

	Word TimeModule::Priority () const noexcept {

		return priority;

	}

	void TimeModule::Install () {

		//	Retrieve settings from the backing
		//	store

		//	Time between ticks
		auto tick_length=RunningServer->Data().GetSetting(tick_length_key);
		if (
			tick_length.IsNull() ||
			!tick_length->ToInteger(&(this->tick_length)) ||
			(this->tick_length==0)
		) this->tick_length=default_tick_length;

		//	Time between saves
		auto between_saves=RunningServer->Data().GetSetting(between_saves_key);
		if (
			between_saves.IsNull() ||
			!between_saves->ToInteger(&(this->between_saves)) ||
			(this->between_saves==0)
		) this->between_saves=default_between_saves;
		else this->between_saves=this->between_saves/this->tick_length;

		//	Offline freeze
		auto offline_freeze=RunningServer->Data().GetSetting(offline_freeze_key);
		this->offline_freeze=(
			offline_freeze.IsNull()
				?	default_offline_freeze
				:	(
						true_regex.IsMatch(*offline_freeze)
							?	true
							:	(
									false_regex.IsMatch(*offline_freeze)
										?	false
										:	default_offline_freeze
								)
					)
		);

		//	Threshold
		auto threshold_percentage=RunningServer->Data().GetSetting(threshold_percentage_key);
		if (
			threshold_percentage.IsNull() ||
			!threshold_percentage->ToInteger(&(this->threshold_percentage))
		) this->threshold_percentage=threshold_percentage_default;

		threshold=static_cast<Word>(
			this->tick_length*(
				static_cast<Double>(
					this->threshold_percentage
				)/100
			)
		)+this->tick_length;

		//	Attempt to load age and time
		TimeSave save;
		Word len=sizeof(save);
		if (
			RunningServer->Data().GetBinary(
				time_key,
				&save,
				&len
			) &&
			(len==sizeof(save))
		) {

			//	Load "hit"

			age=save.Age;
			time=save.Time;

		}

		//	Start timer
		timer=Timer::CreateAndStart();

		//	Start the tick loop
		RunningServer->OnInstall.Add(
			[this] (bool before) {

				if (!before) {

					RunningServer->Pool().Enqueue(
						this->tick_length,
						[this] () {	tick();	}
					);

				}

			}
		);

	}

	LunarPhase TimeModule::get_lunar_phase () const noexcept {

		//	Determine the phase of the
		//	lunar cycle we're in by
		//	first determining the number
		//	of ticks we are into this
		//	lunar cycle, and then using
		//	that to determine how many
		//	days we are into this lunar
		//	cycle
		return static_cast<LunarPhase>((time%(day_length*num_lunar_phases))/day_length);

	}

	UInt64 TimeModule::get_time (bool total) const noexcept {

		//	If we're getting the total,
		//	return exactly the current
		//	time
		if (total) return time;

		//	Otherwise return the number
		//	of ticks since midnight
		return time%day_length;

	}

	TimeOfDay TimeModule::get_time_of_day () const noexcept {

		if (
			(time<4200) ||
			(time>=19800)
		) return TimeOfDay::Night;

		if (time<6000) return TimeOfDay::Dawn;

		if (time<18000) return TimeOfDay::Day;

		return TimeOfDay::Dusk;

	}

	LunarPhase TimeModule::GetLunarPhase () const noexcept {

		return lock.Execute([&] () {	return get_lunar_phase();	});

	}

	UInt64 TimeModule::GetTime (bool total) const noexcept {

		return lock.Execute([&] () {	return get_time(total);	});

	}

	TimeOfDay TimeModule::GetTimeOfDay () const noexcept {

		return lock.Execute([&] () {	return get_time_of_day();	});

	}

	UInt64 TimeModule::GetAge () const noexcept {

		return lock.Execute([&] () {	return age;	});

	}

	Tuple<UInt64,UInt64,LunarPhase,TimeOfDay,UInt64> TimeModule::Get () const noexcept {

		return lock.Execute([&] () {

			return Tuple<UInt64,UInt64,LunarPhase,TimeOfDay,UInt64>(
				get_time(true),
				get_time(false),
				get_lunar_phase(),
				get_time_of_day(),
				age
			);

		});

	}

	void TimeModule::Add (UInt64 ticks) noexcept {

		lock.Acquire();
		time+=ticks;
		lock.Release();

	}

	void TimeModule::Subtract (UInt64 ticks) noexcept {

		lock.Acquire();
		//	If we'd cause an underflow, add enough
		//	days to the time not to
		if (ticks>time) time+=((ticks/day_length)+1)*day_length;
		time-=ticks;
		lock.Release();

	}

	void TimeModule::Set (UInt64 time, bool total) noexcept {

		if (total) {

			//	Set time exactly

			lock.Acquire();
			this->time=time;
			lock.Release();

		} else {

			//	Set elapsed time since
			//	midnight

			//	Determine the offset from
			//	midnight to which the parameter
			//	refers
			time%=day_length;

			lock.Acquire();

			//	Determine the offset from
			//	midnight of the current time
			UInt64 offset=this->time%day_length;

			//	Adjust current time so that
			//	the offset from midnight is
			//	the same
			if (offset<time) this->time+=time-offset;
			else this->time-=offset-time;

			lock.Release();

		}

	}

	void TimeModule::Save () const {

		lock.Acquire();
		UInt64 age=this->age;
		UInt64 time=this->time;
		lock.Release();

		save(age,time);

	}

	void TimeModule::save (UInt64 age, UInt64 time) const {

		TimeSave save{
			age,
			time
		};

		RunningServer->Data().SaveBinary(
			time_key,
			&save,
			sizeof(save)
		);

	}

	void TimeModule::tick () {

		try {

			//	Triggers the next tick
			MultiScopeGuard sg(
				[this] () {

					//	Number of milliseconds since last
					//	tick
					auto elapsed=timer.ElapsedMilliseconds();

					//	How long do we have to wait
					//	for the next tick?
					auto wait=tick_length-elapsed;

					executing+=tick_length-wait;

					//	Enqueue next tick
					RunningServer->Pool().Enqueue(
						(elapsed>=tick_length) ? 0 : wait,
						[this] () {	tick();	}
					);

				},
				//	Do nothing as each scope
				//	guard goes out of scope
				std::function<void ()>(),
				[] () {

					try {

						RunningServer->WriteLog(
							tick_error,
							Service::LogType::Error
						);

					} catch (...) {	}

					RunningServer->Panic();

				}
			);

			//	How long since the last tick?
			Word elapsed=static_cast<Word>(
				timer.ElapsedMilliseconds()
			);

			//	New tick
			timer=Timer::CreateAndStart();
			++ticks;
			tick_time+=elapsed;

			if (elapsed>threshold) {

				//	Tick was "too long"

				RunningServer->WriteLog(
					String::Format(
						tick_too_long,
						(static_cast<Double>(elapsed-tick_length)/tick_length)*100,
						elapsed,
						tick_length
					),
					Service::LogType::Warning
				);

			}

			//	New tick
			timer=Timer::CreateAndStart();

			if (!(
				offline_freeze &&
				(RunningServer->Clients.AuthenticatedCount()==0)
			)) {

				//	We're ticking

				//	Increment
				lock.Acquire();
				UInt64 age=++this->age;
				UInt64 time=++this->time;
				lock.Release();

				//	Send tick packet
				Packet packet;
				packet.SetType<PacketTypeMap<0x04>>();
				packet.Retrieve<UInt64>(0)=age;
				packet.Retrieve<UInt64>(1)=time;

				//	Send to all clients
				RunningServer->Clients.Scan([&] (SmartPointer<Client> & client) {

					if (client->GetState()==ClientState::Authenticated) client->Send(packet);

				});

				//	Execute tasks

				//	Tasks that are executed every
				//	tick
				for (const auto & t : callbacks) {

					//	Will we wait for this callback
					//	or not?
					MultiScopeGuard param;
					if (t.Item<1>()) param=sg;

					RunningServer->Pool().Enqueue(
						t.Item<0>(),
						std::move(param)
					);

				}

				//	Tasks that have been scheduled
				//	to be executed
				while (
					(scheduled_callbacks.Count()!=0) &&
					(scheduled_callbacks[0].Item<0>()>=ticks)
				) {

					//	Will we wait for this task
					//	or not?
					MultiScopeGuard param;
					if (scheduled_callbacks[0].Item<2>()) param=sg;

					auto callback=std::move(scheduled_callbacks[0].Item<1>());

					scheduled_callbacks.Delete(0);

					RunningServer->Pool().Enqueue(
						std::move(callback),
						std::move(param)
					);

				}

			}

			//	It's been one more tick
			//	since we last saved the
			//	age and time to the backing
			//	store
			if ((++since)==between_saves) {

				//	We must save

				since=0;

				save(age,time);

			}

		} catch (...) {

			try {

				RunningServer->WriteLog(
					tick_error,
					Service::LogType::Error
				);

			} catch (...) {	}

			RunningServer->Panic();

			throw;

		}

	}

	Nullable<TimeModule> Time;

}

extern "C" {

	Module * Load () {

		if (Time.IsNull()) Time.Construct();

		return &(*Time);

	}

	void Unload () {

		Time.Destroy();

	}

}
<commit_msg>Time Update<commit_after>#include <time/time.hpp>
#include <packet.hpp>
#include <client.hpp>
#include <data_provider.hpp>
#include <thread_pool.hpp>
#include <cstddef>

namespace MCPP {

	class TimeSave {

		public:

			UInt64 Age;
			UInt64 Time;

	};

	#pragma GCC diagnostic push
	#pragma GCC diagnostic ignored "-Winvalid-offsetof"
	static_assert(
		offsetof(TimeSave,Time)==(offsetof(TimeSave,Age)+sizeof(UInt64)),
		"TimeSave layout incorrect"
	);
	#pragma GCC diagnostic pop

	static const String name("Time Module");
	static const Word priority=1;

	static const Word default_tick_length=50;
	static const Word day_length=24000;
	static const Word default_between_saves=5*60*20;	//	5 minutes
	static const bool default_offline_freeze=true;
	static const Word num_lunar_phases=8;
	static const Word threshold_percentage_default=10;	//	10%

	static const String time_key("time");
	static const String tick_length_key("tick_length");
	static const String offline_freeze_key("offline_freeze");
	static const String between_saves_key("maintenance_interval");
	static const String tick_error("Error while ticking");
	static const String tick_too_long("Tick took {0}% too long - Actual: {1}ms - Expected: {2}ms");
	static const String threshold_percentage_key("tick_threshold");
	static const Regex true_regex(
		"^\\s*(?:t(?:rue)?|y(?:es)?)\\s*$",
		RegexOptions().SetIgnoreCase()
	);
	static const Regex false_regex(
		"^\\s*(?:f(?:alse)?|n(?:o)?)\\s*$",
		RegexOptions().SetIgnoreCase()
	);

	static const String full_moon("Full");
	static const String waning_gibbous_moon("Waning Gibbous");
	static const String last_quarter_moon("Last Quarter");
	static const String waning_crescent_moon("Waning Crescent");
	static const String new_moon("New");
	static const String waxing_crescent_moon("Waxing Crescent");
	static const String first_quarter_moon("First Quarter");
	static const String waxing_gibbous_moon("Waxing Gibbous");

	const String & TimeModule::GetLunarPhase (LunarPhase phase) noexcept {

		switch (phase) {

			case LunarPhase::Full:
			default:return full_moon;

			case LunarPhase::WaningGibbous:return waning_gibbous_moon;

			case LunarPhase::LastQuarter:return last_quarter_moon;

			case LunarPhase::WaningCrescent:return waning_crescent_moon;

			case LunarPhase::New:return new_moon;

			case LunarPhase::WaxingCrescent:return waxing_crescent_moon;

			case LunarPhase::FirstQuarter:return first_quarter_moon;

			case LunarPhase::WaxingGibbous:return waxing_gibbous_moon;

		}

	}

	static const String day("Day");
	static const String dusk("Dusk");
	static const String dawn("Dawn");
	static const String night("Night");

	const String & TimeModule::GetTimeOfDay (TimeOfDay time_of_day) noexcept {

		switch (time_of_day) {

			case TimeOfDay::Day:
			default:return day;

			case TimeOfDay::Dusk:return dusk;

			case TimeOfDay::Night:return night;

			case TimeOfDay::Dawn:return dawn;

		}

	}

	TimeModule::TimeModule () noexcept {

		ticks=0;
		tick_time=0;
		executing=0;
		age=0;
		time=0;
		since=0;

	}

	const String & TimeModule::Name () const noexcept {

		return name;

	}

	Word TimeModule::Priority () const noexcept {

		return priority;

	}

	void TimeModule::Install () {

		//	Retrieve settings from the backing
		//	store

		//	Time between ticks
		auto tick_length=RunningServer->Data().GetSetting(tick_length_key);
		if (
			tick_length.IsNull() ||
			!tick_length->ToInteger(&(this->tick_length)) ||
			(this->tick_length==0)
		) this->tick_length=default_tick_length;

		//	Time between saves
		auto between_saves=RunningServer->Data().GetSetting(between_saves_key);
		if (
			between_saves.IsNull() ||
			!between_saves->ToInteger(&(this->between_saves)) ||
			(this->between_saves==0)
		) this->between_saves=default_between_saves;
		else this->between_saves=this->between_saves/this->tick_length;

		//	Offline freeze
		auto offline_freeze=RunningServer->Data().GetSetting(offline_freeze_key);
		this->offline_freeze=(
			offline_freeze.IsNull()
				?	default_offline_freeze
				:	(
						true_regex.IsMatch(*offline_freeze)
							?	true
							:	(
									false_regex.IsMatch(*offline_freeze)
										?	false
										:	default_offline_freeze
								)
					)
		);

		//	Threshold
		auto threshold_percentage=RunningServer->Data().GetSetting(threshold_percentage_key);
		if (
			threshold_percentage.IsNull() ||
			!threshold_percentage->ToInteger(&(this->threshold_percentage))
		) this->threshold_percentage=threshold_percentage_default;

		threshold=static_cast<Word>(
			this->tick_length*(
				static_cast<Double>(
					this->threshold_percentage
				)/100
			)
		)+this->tick_length;

		//	Attempt to load age and time
		TimeSave save;
		Word len=sizeof(save);
		if (
			RunningServer->Data().GetBinary(
				time_key,
				&save,
				&len
			) &&
			(len==sizeof(save))
		) {

			//	Load "hit"

			age=save.Age;
			time=save.Time;

		}

		//	Start timer
		timer=Timer::CreateAndStart();

		//	Start the tick loop
		RunningServer->OnInstall.Add(
			[this] (bool before) {

				if (!before) {

					RunningServer->Pool().Enqueue(
						this->tick_length,
						[this] () {	tick();	}
					);

				}

			}
		);

	}

	LunarPhase TimeModule::get_lunar_phase () const noexcept {

		//	Determine the phase of the
		//	lunar cycle we're in by
		//	first determining the number
		//	of ticks we are into this
		//	lunar cycle, and then using
		//	that to determine how many
		//	days we are into this lunar
		//	cycle
		return static_cast<LunarPhase>((time%(day_length*num_lunar_phases))/day_length);

	}

	UInt64 TimeModule::get_time (bool total) const noexcept {

		//	If we're getting the total,
		//	return exactly the current
		//	time
		if (total) return time;

		//	Otherwise return the number
		//	of ticks since midnight
		return time%day_length;

	}

	TimeOfDay TimeModule::get_time_of_day () const noexcept {

		if (
			(time<4200) ||
			(time>=19800)
		) return TimeOfDay::Night;

		if (time<6000) return TimeOfDay::Dawn;

		if (time<18000) return TimeOfDay::Day;

		return TimeOfDay::Dusk;

	}

	LunarPhase TimeModule::GetLunarPhase () const noexcept {

		return lock.Execute([&] () {	return get_lunar_phase();	});

	}

	UInt64 TimeModule::GetTime (bool total) const noexcept {

		return lock.Execute([&] () {	return get_time(total);	});

	}

	TimeOfDay TimeModule::GetTimeOfDay () const noexcept {

		return lock.Execute([&] () {	return get_time_of_day();	});

	}

	UInt64 TimeModule::GetAge () const noexcept {

		return lock.Execute([&] () {	return age;	});

	}

	Tuple<UInt64,UInt64,LunarPhase,TimeOfDay,UInt64> TimeModule::Get () const noexcept {

		return lock.Execute([&] () {

			return Tuple<UInt64,UInt64,LunarPhase,TimeOfDay,UInt64>(
				get_time(true),
				get_time(false),
				get_lunar_phase(),
				get_time_of_day(),
				age
			);

		});

	}

	void TimeModule::Add (UInt64 ticks) noexcept {

		lock.Acquire();
		time+=ticks;
		lock.Release();

	}

	void TimeModule::Subtract (UInt64 ticks) noexcept {

		lock.Acquire();
		//	If we'd cause an underflow, add enough
		//	days to the time not to
		if (ticks>time) time+=((ticks/day_length)+1)*day_length;
		time-=ticks;
		lock.Release();

	}

	void TimeModule::Set (UInt64 time, bool total) noexcept {

		if (total) {

			//	Set time exactly

			lock.Acquire();
			this->time=time;
			lock.Release();

		} else {

			//	Set elapsed time since
			//	midnight

			//	Determine the offset from
			//	midnight to which the parameter
			//	refers
			time%=day_length;

			lock.Acquire();

			//	Determine the offset from
			//	midnight of the current time
			UInt64 offset=this->time%day_length;

			//	Adjust current time so that
			//	the offset from midnight is
			//	the same
			if (offset<time) this->time+=time-offset;
			else this->time-=offset-time;

			lock.Release();

		}

	}

	void TimeModule::Save () const {

		lock.Acquire();
		UInt64 age=this->age;
		UInt64 time=this->time;
		lock.Release();

		save(age,time);

	}

	void TimeModule::save (UInt64 age, UInt64 time) const {

		TimeSave save{
			age,
			time
		};

		RunningServer->Data().SaveBinary(
			time_key,
			&save,
			sizeof(save)
		);

	}

	void TimeModule::tick () {

		try {

			//	Triggers the next tick
			MultiScopeGuard sg(
				[this] () {

					//	Number of milliseconds since last
					//	tick
					auto elapsed=timer.ElapsedMilliseconds();

					executing+=elapsed;

					//	If we've been processing for too long,
					//	enqueue for immediate execution,
					//	otherwise wait for the appropriate
					//	amount of time
					Word wait=(elapsed>tick_length) ? 0 : (tick_length-static_cast<Word>(elapsed));

					//	Enqueue next tick
					RunningServer->Pool().Enqueue(
						(elapsed>=tick_length) ? 0 : wait,
						[this] () {	tick();	}
					);

				},
				//	Do nothing as each scope
				//	guard goes out of scope
				std::function<void ()>(),
				[] () {

					try {

						RunningServer->WriteLog(
							tick_error,
							Service::LogType::Error
						);

					} catch (...) {	}

					RunningServer->Panic();

				}
			);

			//	How long since the last tick?
			Word elapsed=static_cast<Word>(
				timer.ElapsedMilliseconds()
			);

			//	New tick
			timer=Timer::CreateAndStart();

			if (!(
				offline_freeze &&
				(RunningServer->Clients.AuthenticatedCount()==0)
			)) {

				//	Update stats
				++ticks;
				tick_time+=elapsed;

				if (elapsed>threshold) {

					//	Tick was "too long"

					Server::Get().WriteLog(
						String::Format(
							tick_too_long,
							(static_cast<Double>(elapsed-tick_length)/tick_length)*100,
							elapsed,
							tick_length
						),
						Service::LogType::Warning
					);

				}

				//	We're ticking

				//	Increment
				lock.Acquire();
				UInt64 age=++this->age;
				UInt64 time=++this->time;
				lock.Release();

				//	Send tick packet
				Packet packet;
				packet.SetType<PacketTypeMap<0x04>>();
				packet.Retrieve<UInt64>(0)=age;
				packet.Retrieve<UInt64>(1)=time;

				//	Send to all clients
				RunningServer->Clients.Scan([&] (SmartPointer<Client> & client) {

					if (client->GetState()==ClientState::Authenticated) client->Send(packet);

				});

				//	Execute tasks

				//	Tasks that are executed every
				//	tick
				for (const auto & t : callbacks) {

					//	Will we wait for this callback
					//	or not?
					MultiScopeGuard param;
					if (t.Item<1>()) param=sg;

					RunningServer->Pool().Enqueue(
						t.Item<0>(),
						std::move(param)
					);

				}

				//	Tasks that have been scheduled
				//	to be executed
				while (
					(scheduled_callbacks.Count()!=0) &&
					(scheduled_callbacks[0].Item<0>()>=ticks)
				) {

					//	Will we wait for this task
					//	or not?
					MultiScopeGuard param;
					if (scheduled_callbacks[0].Item<2>()) param=sg;

					auto callback=std::move(scheduled_callbacks[0].Item<1>());

					scheduled_callbacks.Delete(0);

					RunningServer->Pool().Enqueue(
						std::move(callback),
						std::move(param)
					);

				}

			}

			//	It's been one more tick
			//	since we last saved the
			//	age and time to the backing
			//	store
			if ((++since)==between_saves) {

				//	We must save

				since=0;

				save(age,time);

			}

		} catch (...) {

			try {

				RunningServer->WriteLog(
					tick_error,
					Service::LogType::Error
				);

			} catch (...) {	}

			RunningServer->Panic();

			throw;

		}

	}

	Nullable<TimeModule> Time;

}

extern "C" {

	Module * Load () {

		if (Time.IsNull()) Time.Construct();

		return &(*Time);

	}

	void Unload () {

		Time.Destroy();

	}

}
<|endoftext|>