text:
namespace LiveDocs.Diagrams.Graph.Executable.UnitTests.Tests
{
    using System;
    using System.Linq;

    using LiveDocs.Diagrams.Graph.Executable.Builders;
    using LiveDocs.Diagrams.Graph.Executable.Models;
    using LiveDocs.Diagrams.Graph.Executable.UnitTests.Attributes;

    using Xunit;

    using Action = LiveDocs.Diagrams.Graph.Executable.Models.Action;

    public class FlowTests
    {
        [Theory]
        [AutoMoqData]
        public void AddingTransitionWithMissingStatesThrowsException(Flow flow, Transition transition)
        {
            Assert.Throws<StateMissingException>(() => flow.AddTransition(transition));
        }

        [Theory]
        [AutoMoqData]
        public void AddingTransitionAndStatesAddsStates(Flow flow, Transition transition)
        {
            flow.AddStatesAndTransition(transition);
            var graph = flow.ToGraph();
            Assert.Equal(2, graph.Vertices.Count());
        }

        [Theory]
        [AutoMoqData]
        public void AddingTransitionAndStatesAddsEdge(Flow flow, Transition transition)
        {
            flow.AddStatesAndTransition(transition);
            var graph = flow.ToGraph();
            Assert.Equal(1, graph.Edges.Count());
        }

        [Theory]
        [AutoMoqData]
        public void AddingStatesWithSameIdsAddsOnce(Flow flow, Guid id)
        {
            var screenOne = new State(id, "State 1");
            var screenTwo = new State(id, "State 2");

            flow.AddState(screenOne);
            flow.AddState(screenTwo);

            var graph = flow.ToGraph();
            Assert.Equal(1, graph.Vertices.Count());
        }
    }
}

redpajama_set_name: RedPajamaGithub


text:
---
layout: post
title:  "CCIA-2-basic-thread-mangement"
date:   2017-03-05 21:06:05
categories: read
tags:  thread c++
---

* content
{:toc}

## 2.1 线程管理的基础 Basic Thread Mangement
每个程序至少有一个线程:执行main()函数的线程,其余线程有其各自的入口函数. 线程与原始线程(以main()为入口函数的线程)同时运行。如同main()函数执行完会退出一样,当线程执行完入口函数后,线程也会退出. 在为一个线程创建了一个 std::thread 对象后,需要等待这个线程结束。
Every C++ program has at least one thread, which is started by the C++ runtime: the thread running main(). Your program can then launch additional threads that have another function as the entry point. These threads then run concurrently with each other and with the initial thread. Just as the program exits when the program returns from main(), when the specified entry point function returns, the thread exits. As you'll see, if you have a std::thread object for a thread, you can wait for it to finish。

### 2.1.1 Launching a thread 启动线程
使用C++线程库启动线程,可以归结为构造 std::thread 对象:
Starting a thread using the C++ Thread Library always boils down to constructing a std::thread object:
```c++
class background_task
{
public:
void operator()() const
{
do_something();
do_something_else();
}
};
background_task f;
std::thread my_thread(f);
```

有件事需要注意,当把函数对象传入到线程构造函数中时,如果你传递了一个临时变量,而不是一个命名的变量;C++编译器会将其解析为函数声明,而不是类型对象的定义。
One thing to consider when passing a function object to the thread constructor is to avoid what is dubbed "C++'s most vexing parse." If you pass a temporary rather Basic thread management 17 than a named variable, then the syntax can be the same as that of a function declaration, in which case the compiler interprets it as such, rather than an object definition.

For example,
```c++
std::thread my_thread(background_task());
```
这里相当与声明了一个名为my_thread的函数,这个函数带有一个参数(函数指针指向没有参
数并返回background_task对象的函数),返回一个 std::thread 对象的函数,而非启动了一个线程。
declares a function my_thread that takes a single parameter (of type pointer to a function taking no parameters and returning a background_task object) and returns a std::thread object, rather than launching a new thread.

使用在前面命名函数对象的方式,或使用多组括号①,或使用新统一的初始化语法②,可以避免这个问题。
You can avoid this by naming your function object as shown previously, by using an extra set of parentheses, or
by using the new uniform initialization syntax, for example:
```c++
// 1
std::thread my_thread((background_task()));
// 2
std::thread my_thread{background_task()};
// 3
std::thread my_thread([]{
do_something();
do_something_else();
});
```

启动了线程,你需要明确是要等待线程结束,还是让其自主运行。如果 std::thread 对象销毁之前还没有做出决定,程序就会终止( std::thread 的析构函数会调用 std::terminate() )。因此,即便是有异常存在,也需要确保线程能够正确的加入(joined)或分离(detached).
It's therefore imperative that you ensure that the thread is correctly joined or detached, even in the presence of exceptions。

如果不等待线程,就必须保证线程结束之前,可访问的数据得有效性。
If you don't wait for your thread to finish, then you need to ensure that the data accessed by the thread is valid until the thread has finished with it.
```c++
//函数已经结束,线程依旧访问局部变量
//A function that returns while a thread still has access to local variables
struct func
{
int& i;
func(int& i_) : i(i_) {}
void operator() ()
{
   for (unsigned j=0 ; j<1000000 ; ++j)
   {
      // 1. 潜在访问隐患:悬空引用 Potential access to dangling reference
      do_something(i);
   }
}
};
void oops()
{
   int some_local_state=0;
   func my_func(some_local_state);
   std::thread my_thread(my_func);
   // 2. 不等待线程结束 do not wait for thread to finish
   my_thread.detach();
} // 3. 函数退出时新线程可能还在运行  New thread might still be running when func exits
```
处理这种情况的常规方法 common way to handle this scenario:
1 数据复制到线程中,而非共享数据
make the thread function self-contained and copy the data into the thread rather than sharing the data。
2 使用一个能访问局部变量的函数去创建线程是一个糟糕的主意(除非十分确定线程会在函数完成前结束,例如使用join see 2.1.2).
repace `my_thread.detach()` with `my_thread.join()`;

### 2.1.2 等待线程完成 Waiting for a thread to complete
join()是简单粗暴的等待线程完成或不等待。当你需要对等待中的线程有更灵活的控制时,比
如,看一下某个线程是否结束,或者只等待一段时间(超过时间就判定为超时)。想要做到这
些,你需要使用其他机制来完成,比如条件变量和期待(futures).
If you need more fine-grained control over waiting for a thread, such as to
check whether a thread is finished, or to wait only a certain period of time, then you
have to use alternative mechanisms such as condition variables and futures。

调用join()的行为,还清理了线程相关的存储部分,这样 std::thread 对象将不再与已经
完成的线程有任何关联。这意味着,只能对一个线程使用一次join();一旦已经使用过
join(), std::thread 对象就不能再次加入了,当对其使用joinable()时,将返回否(false)。
The act of calling join() also cleans up any storage associated
with the thread, so the std::thread object is no longer associated with the now finished
thread; it isn't associated with any thread. This means that you can call
join() only once for a given thread; once you've called join(), the std::thread
object is no longer joinable, and joinable() will return false.

#### 2.1.2.1 特殊情况下的等待  Waiting in exceptional circumstances
如前所述,需要对一个还未销毁的 std::thread 对象使用join()或detach()。如果想要分离一
个线程,可以在线程启动后,直接使用detach()进行分离。如果打算等待对应线程,则需要细
心挑选调用join()的位置。当在线程运行之后产生异常,在join()调用之前抛出,就意味着很这
次调用会被跳过.
you need to ensure that you've called either join() or detach() before a std::thread object is destroyed.
If you're detaching a thread, you can usually call detach() immediately after the thread has been started, so this isn't a
problem. But if you're intending to wait for the thread, you need to pick carefully the place in the code where you call join(). This means that the call to join() is liable to be skipped if an exception is thrown after the thread has been started but before the call to join().

Solotion is shown below:
```c++
// solution 1 add join() in all exit palces
struct func;
void f()
{
   int some_local_state=0;
   func my_func(some_local_state);
   std::thread t(my_func);
try
{
   do_something_in_current_thread();
}
catch(...)
{
   t.join(); // 1
   throw;
}
t.join(); // 2
}

// solution 2 is using RAII to wait for a thread to complete
// it is easier than s0lution 1
class thread_guard
{
   std::thread& t;
   public:
   explicit thread_guard(std::thread& t_):
   t(t_){}
   ~thread_guard()
   {
      if(t.joinable())
      {
         t.join();
      }
   }
   thread_guard(thread_guard const&)=delete;
   thread_guard& operator=(thread_guard const&)=delete;
};
struct func;
void f()
{
   int some_local_state=0;
   func my_func(some_local_state);
   std::thread t(my_func);
   thread_guard g(t);
   do_something_in_current_thread();
}
```

### 2.1.3 后台运行线程 Running threads in the background
如果线程分离,那么就不可能有 std::thread 对象能引用它,分离线程
的确在后台运行,所以分离线程不能被加入. C++运行库保证,当线程退出时,
相关资源的能够正确回收,后台线程的归属和控制C++运行库都会处理.
if a thread becomes detached, it isn't possible to obtain a
std::thread object that references it, so it can no longer be joined. Detached threads
truly run in the background; ownership and control are passed over to the C++ Runtime
Library, which ensures that the resources associated with the thread are correctly
reclaimed when the thread exits.

这种线程的特点就是长时间运行;线程的生命周期可能会从某一个应用起始到结束,可能会在后台监视文件系统,还有可能对缓存进行清理,亦或对数据结构进行优化.
Such threads are typically long-running; they may well run for almost the entire lifetime of
the application, performing a background task such as monitoring the filesystem,
clearing unused entries out of object caches, or optimizing data structures.

如果不是后台线程,但是若能确定该线程什么时候结束,或者是"发后即忘"(fire andforget)的任务的也可以使用detached线程。
At the other extreme, it may make sense to use a detached thread where there's another
mechanism for identifying when the thread has completed or where the thread is
used for a "fire and forget" task.
```c++
void edit_document(std::string const& filename)
{
   open_document_and_display_gui(filename);
   while(!done_editing())
   {
   user_command cmd=get_user_input();
   if(cmd.type==open_new_document)
   {
      std::string const new_name=get_filename_from_user();
      std::thread t(edit_document,new_name); // 1
      t.detach(); // 2
   }
   else
   {
      process_user_input(cmd);
   }
}
}
```

## 2.2 向线程函数传递参数 Passing arguments to a thread function
需要注意的是,默认参数要拷贝到线程独立内存中,即使参数是引用的形式。
it's important to bear in mind that by default the arguments are copied into internal
storage, where they can be accessed by the newly created thread of execution,
even if the corresponding parameter in the function is expecting a reference。
```c++
void f(int i, std::string const& s);
std::thread t(f, 3, "hello");
```
代码创建了一个调用f(3, "hello")的线程。注意,函数f需要一个 std::string 对象作为第二个
参数,但这里使用的是字符串的字面值,也就是 char const * 类型。之后,在线程的上下文
中完成字面值向 std::string 对象的转化。需要特别要注意,当指向动态变量的指针作为参数
传递给线程的情况,代码如下:
This creates a new thread of execution associated with t, which calls f(3,"hello").
Note that even though f takes a std::string as the second parameter, the string literal
is passed as a char const* and converted to a std::string only in the context of
the new thread. This is particularly important when the argument supplied is a
pointer to an automatic variable, as follows:
```c++
void f(int i,std::string const& s);
void oops(int some_param)
{
char buffer[1024]; // 1
sprintf(buffer, "%i",some_param);
std::thread t(f,3,buffer); // 2
t.detach();
}
```
这种情况下,buffer②是一个指针变量,指向本地变量,通过std::thread对象构造函数copy到thread内部成员中②。然而,oops函数有很大的可能,会在thread将字面值转化成 std::string 对象之前exit,从而导致线程的一些未定义行为。解决方案就是将字面值转化为 std::string 对象,然后传递给thread,从而拷贝buffer到thread中去.
In this case, it's the pointer to the local variable buffer B that's passed through to the
new thread c, and there's a significant chance that the function oops will exit before
the buffer has been converted to a std::string on the new thread, thus leading to
undefined behavior. The solution is to cast to std::string before passing the buffer
to the std::thread constructor.(thread's ctor is inviked on the new thread execution).
```c++
void f(int i,std::string const& s);
void not_oops(int some_param)
{
char buffer[1024];
sprintf(buffer,"%i",some_param);
// 使用std::string,避免悬垂指针 Using std::string avoids dangling pointer
std::thread t(f,3,std::string(buffer));
// poesudo code in constructor of thread
// std::string internal_str = std::string(buffer); // value-copy
t.detach();
}
```
不过,也有相反的情况:你想要的就是引用拷贝 而非默认的值拷贝,你需要更新你传递的引用,例如:
It's also possible to get the reverse scenario: the object is copied, and what you
wanted was a reference. This might happen if the thread is updating a data structure
that's passed in by reference, for example:
```c++
void update_data_for_widget(widget_id w,widget_data& data); // 1
void oops_again(widget_id w)
{
   widget_data data;
   std::thread t(update_data_for_widget,w,data); // 2
   display_status();
   t.join();
   process_widget_data(data); // 3
}
```
当线程调用
update_data_for_widget函数时,传递给函数的参数是data变量内部拷贝的引用,而非数据本
身的引用。因此,当线程结束时,内部拷贝数据将会在数据更新阶段被销毁,且 process_widget_data将会接收到没有修改的data变量③。
使用 std::bind ,就可以解决这个问题,使用 std::ref 将参数转换成引用的形式。这种情况下,可将线程的调用,改成以下形式:
Consequently, when the
thread finishes, these updates will be discarded as the internal copies of the supplied arguments are destroyed, and process_widget_data will be passed an unchanged data d rather than a correctly updated version. you need to wrap the arguments that really need to be references in std::ref. In this case, if you change the thread invocation to:
```c++
std::thread t(update_data_for_widget,w,std::ref(data));
```

## 2.3 Transferring ownership of a thread 转移线程所有权
假设要写一个函数,该函数会创建一个运行在后台的新线程, 并且会返回该线程的所有权给函数调用者;
或完全与之相反:创建一个线程,并将所有权通过参数传递给另外一个函数,并且在该函数作用域内join该线程。
总之,新线程的所有权都需要转移。 明执行线程的所有权可以在 std::thread 实例中移动,下面将展示一个例
子。例子中,创建了两个执行线程,并且在 std::thread 实例之间(t1,t2和t3)转移所有权:
the ownership of a particular thread of execution can be moved between std::thread instances, as in the following example. The example 26 CHAPTER 2 Managing threads shows the creation of two threads of execution and the transfer of ownership of those threads among three std::thread instances, t1, t2, and t3:
```c++
void some_function();
void some_other_function();

/* 1 a new thread is started and associated with t1. */
std::thread t1(some_function);

/* 2
 * ownership is then transferred over to t2 when t2 is constructed,
 * by invoking std::move() to explicitly move ownership.
 * At this point, t1 no longer has an associated thread of execution;
 * the thread running some_function is now associated with t2.
 */
std::thread t2=std::move(t1);

/* 3
 * Then, a new thread is started and associated with a temporary std::thread
 * object d. The subsequent transfer of ownership into t1 doesn't require a call to std::
 * move() to explicitly move ownership, because the owner is a temporary object—moving
 * from temporaries is automatic and implicit.
 */
t1=std::thread(some_other_function);

/* 4
 * t3 is default constructed e, which means that it's created without any associated
 * thread of execution. Ownership of the thread currently associated with t2 is transferred
 * into t3 f, again with an explicit call to std::move(), because t2 is a named object. After
 * all these moves, t1 is associated with the thread running some_other_function, t2 has no
 * associated thread, and t3 is associated with the thread running some_function.
 */
std::thread t3;
t3=std::move(t2);

/* 5
 * The final move g transfers ownership of the thread running some_function back
 * to t1 where it started. But in this case t1 already had an associated thread (which was
 * running some_other_function), so std::terminate() is called to terminate the
 * program. This is done for consistency with the std::thread destructor. You saw in
 * section 2.1.1 that you must explicitly wait for a thread to complete or detach it before
 * destruction, and the same applies to assignment: you can't just "drop" a thread by
 * assigning a new value to the std::thread object that manages it.
 */
t1=std::move(t3); // 赋值操作将使程序崩溃 This assignment will terminate program!
```
The move support in std::thread means that ownership can readily be transferred out of a function:
```c++
// 函数返回 std::thread 对象 Returning a std::thread from a function
std::thread f()
{
   void some_function();
   return std::thread(some_function);
}
std::thread g()
{
   void some_other_function(int);
   std::thread t(some_other_function,42);
   return t;
}
```

Likewise, if ownership should be transferred into a function, it can just accept an
instance of std::thread by value as one of the parameters, as shown here:
```c++
// 传递 std::thread 对象到函数 pass in a std::thread to a function
void f(std::thread t);
void g()
{
void some_function();
// tempory thread instance and use std::move implicitely
f(std::thread(some_function));
std::thread t(some_function);
// named thread instance t and so has to use std::move explicitely
f(std::move(t));
}
```

```c++
class scoped_thread
{
std::thread t;
public:
explicit scoped_thread(std::thread t_): // 1
t(std::move(t_))
{
if(!t.joinable()) // 2
throw std::logic_error("No thread");
}
~scoped_thread()
{
t.join(); // 3
}
scoped_thread(scoped_thread const&)=delete;
scoped_thread& operator=(scoped_thread const&)=delete;
};
struct func;
void f()
{
int some_local_state;
scoped_thread t(std::thread(func(some_local_state))); // 4
do_something_in_current_thread();
}
```

std::thread 对象的容器,如果这个容器是移动敏感的(比如,标准中的 std::vector<> ),那么移动操作同样适用于这些容器.
The move support in std::thread also allows for containers of std::thread objects, if those containers are move aware (like the updated std::vector<>).
```c++
void do_work(unsigned id);
void f()
{
std::vector<std::thread> threads;
for(unsigned i=0; i < 20; ++i)
{
threads.push_back(std::thread(do_work,i)); // 产生线程 spawn threads
}
std::for_each(threads.begin(),threads.end(),
std::mem_fn(&std::thread::join)); // 对每个线程调用join() call join on each thread
}
```

## 2.4 运行时决定线程数量
将 std::thread 放入 std::vector 是向线程自动化管理迈出的第一步:并非为这些线程创建独
立的变量,并且将他们直接加入,可以把它们当做一个组。创建一组线程(数量在运行时确定),可使得这一步迈的更大.
Putting std::thread objects in a std::vector is a step toward automating the management of those threads. You can take this a step further by creating a dynamic number of threads determined at runtime.
```c++
template<typename Iterator,typename T>
struct accumulate_block
{
void operator()(Iterator first,Iterator last,T& result)
{
result=std::accumulate(first,last,result);
}
};
template<typename Iterator,typename T>
T parallel_accumulate(Iterator first,Iterator last,T init)
{
unsigned long const length=std::distance(first,last);
if(!length) // 1
return init;
unsigned long const min_per_thread=25;
unsigned long const max_threads=
(length+min_per_thread-1)/min_per_thread; // 2
unsigned long const hardware_threads=
std::thread::hardware_concurrency();
unsigned long const num_threads= // 3
std::min(hardware_threads != 0 ? hardware_threads : 2, max_threads);
unsigned long const block_size=length/num_threads; // 4
std::vector<T> results(num_threads);
std::vector<std::thread> threads(num_threads-1); // 5
Iterator block_start=first;
for(unsigned long i=0; i < (num_threads-1); ++i)
{
Iterator block_end=block_start;
std::advance(block_end,block_size); // 6
threads[i]=std::thread( // 7
accumulate_block<Iterator,T>(),
block_start,block_end,std::ref(results[i]));
block_start=block_end; // 8
}
accumulate_block<Iterator,T>()(
block_start,last,results[num_threads-1]); // 9
std::for_each(threads.begin(),threads.end(),
std::mem_fn(&std::thread::join)); // 10
return std::accumulate(results.begin(),results.end(),init); // 11
}
```

## 2.5 识别线程 Identifying
First, the identifier for a thread can be obtained from its associated std::thread object by calling the get_id() member function. returns a defaultconstructed std::thread::id object, which indicates "no any thread.".
线程标识类型是 std::thread::id ,可以通过两种方式进行检索。第一种,可以通过调用 std::thread 对象的成员函数 get_id() 来直接获取。如果 std::thread 对象没有与任何执行线程相关联, get_id() 将返回 std::thread::type 默认构造值,这个值表示"没有线程"。第二种,当前线程中调用 std::this_thread::get_id().

threadsstd::thread::id 类型对象提供相当丰富的对比操作;比如,提供为不同的值进行排序. 标准库也提供 std::hash<std::thread::id> 容器,所以 std::thread::id 也可以作为无序容器的键值。
```c++
std::thread::id master_thread;
void some_core_part_of_algorithm()
{
if(std::this_thread::get_id()==master_thread)
{
do_master_thread_work();
}
do_common_work();
}
```
std::thread::id 可以作为一个线程的通用标识符,当标识符只与语义相关(比如,数组的索
引)时,就需要想其他办法了(例如之前例子中只用循环中的index作为线程的标识)。
The idea is that std::thread::id will suffice as a generic identifier for a thread in
most circumstances; it's only if the identifier has semantic meaning associated with it
(such as being an index into an array) that alternatives should be necessary.


text:
declare const ImagesIcon: () => JSX.Element
export default ImagesIcon


text:
<?php defined('BASEPATH') OR exit('No direct script access allowed');

class Admin extends CI_Controller {

    public function __construct()
    {
        parent::__construct();
        $this->load->model('admin_model');
        $this->load->library('twig');
        //$this->output->cache(5);
    }

    private function _admin_access()
    {
        if ($this->session->has_userdata('login') != NULL &&
            $this->session->userdata('user_rights') == $this->config->item('admin_rights') &&
            $this->session->userdata('user_enabled') == $this->config->item('STATUS_ON'))
        {
            return TRUE;
        }

        return FALSE;
    }

    public function index($data = '')
    {
        $data['title'] = 'Административная панель';

        if ($this->_admin_access() === true)
        {
            $data['page_name'] = 'Основная панель';
            $data['user_name'] = $_SESSION['login'];
            $data['comments'] = $this->admin_model->get_comments('4');
            $data['requests'] = $this->admin_model->get_requests('4');
            //$data['orders'] = $this->admin_model->get_orders('4');

            $data['method'] = 'index';
            $data['table1'] = 'order_for_assessment';
            $data['table2'] = 'comments';

            echo $this->twig->render('admin/main', $data);
        }

        elseif ($this->session->has_userdata('login') != NULL && ($this->session->userdata('user_rights') !== $this->config->item('admin_rights') OR  $this->session->userdata('user_enabled') == $this->config->item('STATUS_OFF')))
        {
            $this->session->sess_destroy();
            $data['error'] = 'У Вас не достаточно прав для доступа к этой странице или пользователь с таким логином выключен';
            $data['user_name'] = $_SESSION['login'];

            // send error to the view
            echo $this->twig->render('user/login/login_admin', $data);
        }

        else
        {
            $this->login();
        }
    }

    /**
     * login function.
     *
     * @access public
     * @return void
     */
    public function login()
    {
        $data['title'] = 'Garage - Авторизация';

        if ($this->_admin_access() === true)
        {
            $this->index();
        }
        else
        {
            $this->load->model('user_model');

            // load form helper and validation library
            $this->load->helper('form');
            $this->load->library('form_validation');

            // set validation rules
            $this->form_validation->set_rules('login', 'Login', 'required|alpha_numeric');
            $this->form_validation->set_rules('password', 'Password', 'required');

            if ($this->form_validation->run() == false)
            {
                // validation not ok, send validation errors to the view
                echo $this->twig->render('user/login/login_admin', $data);
            }

            else
            {
                // set variables from the form
                $login = $this->input->post('login');
                $password = $this->input->post('password');

                if ($this->user_model->resolve_user_login($login, $password))
                {
                    $user_id = $this->user_model->get_user_id_from_username($login);
                    $user    = $this->user_model->get_user($user_id);
                    $user_data = $this->user_model->get_user_data($user_id);

                    //set session user data
                    $session_data = array(
                                    'id' => session_id(),
                                    'user_id' => (int)$user->id,
                                    'login' => (string)$user->login,
                                    'logged_in' => (bool)true,
                                    'user_enabled' => (int)$user_data->user_enabled,
                                    'user_rights' => (int)$user_data->user_rights, );

                    $this->session->set_userdata($session_data);

                    if ($this->session->userdata('user_rights') == $this->config->item('admin_rights'))
                    {
                        $this->user_model->set_user_session();

                        // user login ok
                        $data['user_login'] = $this->session->userdata('login');
                        echo $this->twig->render('user/login/login_admin_success', $data);
                    }

                    else
                    {
                        // login failed
                        $data['error'] = 'У Вас не достаточно прав для доступа к этой странице';

                        // send error to the view
                        echo $this->twig->render('user/login/login_admin', $data);
                    }
                }

                else
                {
                    // login failed
                    $data['error'] = 'Неверный логин или пароль. Повторите ввод.';

                    // send error to the view
                    echo $this->twig->render('user/login/login_admin', $data);
                }
            }
        }
    }

    /**
     * logout function for admin panel.
     *
     * @access public
     * @return void
     */
    public function logout()
    {
        $data['title'] = 'Garage - Авторизация';

        if ($this->session->has_userdata('logged_in') != NULL && $this->session->userdata('logged_in') === true)
        {
            $data['user_login'] = $this->session->userdata('login');
            $this->session->sess_destroy();

            // user logout ok
            echo $this->twig->render('user/logout/logout_admin_success', $data);
        }

        else
        {
            // there user was not logged in, we cannot logged him out,
            // redirect him to site root
            redirect('/');
        }
    }

    //metods for work with data in admin panel
    public function show_articles($data = '', $id = '')
    {
        if ($this->_admin_access() === true)
        {
            $data['articles'] = $this->admin_model->get_article($id);
            $data['user_name'] = $_SESSION['login'];
            $data['page_name'] = 'Управление контентом';

            $data['method'] = 'show_articles';
            $data['table'] = 'Content';

            echo $this->twig->render('admin/all_articles_view', $data);
        }
        else
        {
            $this->login();
        }
    }

    public function show_users($data = '')
    {
        if ($this->_admin_access() === true)
        {
            $this->load->model('user_model');
            $data['users'] = $this->user_model->get_user_info();
            $data['user_name'] = $_SESSION['login'];
            $data['page_name'] = 'Просмотр пользователей';

            $data['method'] = 'show_users';
            $data['table'] = 'users';

            echo $this->twig->render('admin/all_users_view', $data);
        }
        else
        {
            $this->login();
        }
    }

    public function show_comments($limit = '0')
    {
        if ($this->_admin_access() === true)
        {
            $data['comments'] = $this->admin_model->get_comments($limit);
            $data['user_name'] = $_SESSION['login'];
            $data['page_name'] = 'Просмотр комментариев';

            $data['method'] = 'show_comments';
            $data['table'] = 'comments';

            echo $this->twig->render('admin/all_comments_view', $data);
        }
        else
        {
            $this->login();
        }
    }

    public function show_requests($limit = '0')
    {
        if ($this->_admin_access() === true)
        {
            $data['requests'] = $this->admin_model->get_requests($limit);
            $data['user_name'] = $_SESSION['login'];
            $data['page_name'] = 'Просмотр запросов на оценку работ';
            $data['method'] = 'show_requests';
            $data['table'] = 'order_for_assessment';
            echo $this->twig->render('admin/pdr_requests_view', $data);
        }
        else
        {
            $this->login();
        }
    }

    public function show_cars()
    {
        if ($this->_admin_access() === true)
        {
            $data['models'] = $this->admin_model->get_cars();
            $data['marks'] = $this->admin_model->get_marks();
            $data['user_name'] = $_SESSION['login'];
            $data['page_name'] = 'Каталог автомобилей';
            echo $this->twig->render('admin/all_avto_view', $data);
        }
        else
        {
            $this->login();
        }
    }

    public function add_car()
    {
        if ($this->_admin_access() === true)
        {
            if ($this->input->post('model') == (null OR ' ') OR $this->input->post('mark') == (null OR ' '))
            {
                $data['error'] = 'Заполните все поля формы';
            }
            else
            {
                $newCar = $this->input->post();
                if ($this->admin_model->add_car($newCar) === false)
                {
                    $data['error'] = 'Ошибка при добавлении авто в базу. Вероятнее всего у этого производителя уже есть авто с таким названием в базе данных';
                }

                $data['info'] = 'Автомобиль успешно добавлен в базу';
            }

            $data['models'] = $this->admin_model->get_cars();
            $data['marks'] = $this->admin_model->get_marks();
            $data['user_name'] = $_SESSION['login'];
            $data['page_name'] = 'Каталог автомобилей';
            echo $this->twig->render('admin/all_avto_view', $data);
        }
        else
        {
            $this->login();
        }
    }

    public function delete_car()
    {
        if ($this->_admin_access() === true)
        {
            if ($this->input->post('ModelName') == null)
            {
                $data['error'] = 'Выберите авто для удаления';
            }

            else
            {
                $model_id = $this->input->post('ModelName');
                if ($this->admin_model->delete_data($model_id, 'cars_model') === false)
                {
                    $data['error'] = 'Ошибка при удалении авто из базы';
                }

                $data['info'] = 'Автомобиль успешно удален из базы';
            }

            $data['models'] = $this->admin_model->get_cars();
            $data['marks'] = $this->admin_model->get_marks();
            $data['user_name'] = $_SESSION['login'];
            $data['page_name'] = 'Каталог автомобилей';
            echo $this->twig->render('admin/all_avto_view', $data);
        }
        else
        {
            $this->login();
        }
    }

    public function add_article()
    {
        if ($this->_admin_access() === true)
        {
            $data = array();

            $this->load->library('form_validation');

            $this->form_validation->set_rules('title', 'Заголовок', 'trim|required');
            $this->form_validation->set_rules('text', 'Содержимое', 'trim|required');
            $this->form_validation->set_rules('meta', 'Теги', 'trim|required');
            $this->form_validation->set_rules('address', 'Адрес', 'trim|required');

            if ($this->form_validation->run() === false)
            {
                $data['user_name'] = $_SESSION['login'];
                $data['page_name'] = 'Управление контентом';
                echo $this->twig->render('admin/add_article_view', $data);
            }

            else
            {
                $this->admin_model->create_content();
                $data['info'] = 'Статья успешно добавлена';
                $this->show_articles($data);
            }
        }

        else
        {
            $this->login();
        }
    }

        public function edit_article($id = '')
    {
        if ($this->_admin_access() === true)

        {
            $data = array();
            $data['get_article'] = $this->admin_model->get_article($id);

            if ($this->form_validation->run() === false)
            {
                $data['user_name'] = $_SESSION['login'];
                $data['page_name'] = 'Редактирование статьи';
                echo $this->twig->render('admin/add_article_view', $data);
            }

            else
            {
                $this->admin_model->edit_content();
                $this->show_articles();
            }
        }

        else
        {
            $this->login();
        }
    }

    public function show_example($data = '', $id = '')
    {
        if ($this->_admin_access() === true)
        {
            $data['examples'] = $this->admin_model->get_example($id);
            $data['user_name'] = $_SESSION['login'];
            $data['page_name'] = 'Управление примерами работ';
            $data['categories'] = $this->config->item("categories");
            $data['method'] = 'show_example';
            $data['table'] = 'example_works';

            echo $this->twig->render('admin/all_examples_view', $data);
        }
        else
        {
            $this->login();
        }
    }

    public function add_example()
    {
        if ($this->_admin_access() === true)
        {
            $data = array();

            $this->load->helper('form');
            $this->load->library('form_validation');
            $data['user_name'] = $_SESSION['login'];

            $this->form_validation->set_rules('category', 'category', 'required');
            $this->form_validation->set_rules('text', 'text', 'trim|required');
            $this->form_validation->set_rules('foto_before', 'foto_before', 'required');
            $this->form_validation->set_rules('foto_after', 'foto_after', 'required');
            $this->form_validation->set_rules('additionally', 'additionally', 'trim|required');

            if ($this->form_validation->run() === false)
            {

                $data['page_name'] = 'Управление примерами работ';
                $data['categories'] = $this->config->item("categories");
                echo $this->twig->render('admin/add_example_view', $data);
            }

            else
            {
                $this->admin_model->create_example();
                $data['page_name'] = 'Просмотр примеров работ';
                $this->show_example();
            }
        }

        else
        {
            $this->login();
        }
    }

    public function add_user()
    {
        if ($this->_admin_access() === true)
        {
            $this->load->helper('form');
            $this->load->library('form_validation');

            $data['user_name'] = $_SESSION['login'];
            $data['page_name'] = 'Управление пользователями';

            $data['models'] = $this->admin_model->get_cars();
            $data['marks'] = $this->admin_model->get_marks();
            $data['user_right'] = array(
                                    'Админ' => $this->config->item('admin_rights'),
                                    'Пользователь' => $this->config->item('user_rights'),);

            // set validation rules
            $this->form_validation->set_rules('login', 'Логин', 'trim|required|alpha_numeric|min_length[3]|is_unique[users.login]', array('is_unique' => 'Этот логин уже занят. Пожалуйста введите другой.'));
            $this->form_validation->set_rules('name', 'Имя', 'trim|required|alpha_numeric|min_length[2]');
            $this->form_validation->set_rules('surname', 'Фамилия', 'trim|required|alpha_numeric|min_length[2]');
            $this->form_validation->set_rules('sex', 'Пол', 'required');
            $this->form_validation->set_rules('birthsday', 'Дата рождения', 'trim|required');
            $this->form_validation->set_rules('email', 'e-mail', 'trim|required|valid_email|is_unique[users.email]', array('is_unique' => 'Данный e-mail уже используется. Пожалуйста введите другой.'));
            $this->form_validation->set_rules('tel', 'Телефон', 'trim|required|alpha_numeric|min_length[10]');
            $this->form_validation->set_rules('password', 'Пароль', 'trim|required|min_length[6]');
            $this->form_validation->set_rules('password_confirm', 'Подтверждение пароля', 'trim|required|min_length[6]|matches[password]');

            if ($this->form_validation->run() === false)
            {
                // validation not ok, send validation errors to the view
                if (validation_errors() == true)
                {
                    $data['error'] = 'Проверьте правильность заполнения всех полей.';
                }

                echo $this->twig->render('admin/add_user_view', $data);
            }

            elseif (($this->input->post('ManufactureName') !== null AND $this->input->post('ModelName') == null) OR ($this->input->post('ManufactureName') == null AND $this->input->post('car_year') !== null))
            {
                $data['error'] = 'Проверьте правильность заполнения полей выбора авто.';
                echo $this->twig->render('admin/add_user_view', $data);
            }

            else
            {
                $this->load->model('user_model');
                $register = $this->input->post();

                if ($this->input->post('status') == 'on')
                {
                    $register['status'] = $this->config->item('STATUS_ON');
                }
                else
                {
                    $register['status'] = $this->config->item('STATUS_OFF');
                }

                if ($this->user_model->create_user($register))
                {
                    // user creation ok
                    $data['info'] = 'Пользователь успешно добавлен.';

                    $this->show_users($data);
                }

                else
                {
                    // user creation failed, this should never happen
                    $data['error'] = 'Что-то пошло не так. Please try again.';

                    // send error to the view
                    echo $this->twig->render('admin/add_user_view', $data);
                }
            }
        }
        else
        {
            $this->login();
        }
    }

    public function show_user($id)
    {
        if ($this->_admin_access() === true)
        {
            $this->load->model('user_model');

            $data['page_name'] = 'Профиль пользователя';
            $data['user_name'] = $_SESSION['login'];
            // $data['comments'] = $this->admin_model->get_comments('4');
            // $data['requests'] = $this->admin_model->get_requests('4');
            //$data['orders'] = $this->admin_model->get_orders('4');

            $data['user'] = $this->user_model->get_user_info($id);
            $data['method'] = 'index';
            $data['table1'] = 'order_for_assessment';
            $data['table2'] = 'comments';

            echo $this->twig->render('admin/user_view', $data);
        }
        else
        {
            $this->login();
        }
    }

    public function change_user_status($id, $status, $data = '')
    {
        if ($this->_admin_access() === true)
        {
            $this->load->model('user_model');

            $data['user_enabled'] = (int)!$status;

            if ($this->user_model->change_user_status($id, $data))
            {
                // user creation ok
                $data['info'] = 'Пользователю успешно изменен статус.';
                $this->show_users($data);
            }

            else
            {
                // user creation failed, this should never happen
                $data['error'] = 'Что-то пошло не так. Please try again.';

                // send error to the view
                echo $this->twig->render('admin/all_user_view', $data);
            }
        }
        else
        {
            $this->login();
        }
    }

    public function delete_item($method, $table, $id)
    {
        if ($this->_admin_access() === true)
        {
            if ($this->admin_model->delete_data($id, $table))
            {
                // item delete ok
                $data['info'] = 'Запись успешно удалена';
                $this->{$method}($data);
            }

            else
            {
                // item delete failed, this should never happen
                $data['error'] = 'Что-то пошло не так. Please try again.';
                $this->{$method}($data);
            }
        }
        else
        {
            $this->login();
        }
    }
}


text:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
	package="com.commonsware.cwac.strict.demo"
	android:versionCode="1"
	android:versionName="1.0">

	<uses-sdk android:minSdkVersion="7"/>

	<application
		android:icon="@drawable/ic_launcher"
		android:label="@string/app_name">
		<activity
			android:name=".StrictModeExDemoActivity"
			android:label="@string/app_name">
			<intent-filter>
				<action android:name="android.intent.action.MAIN"/>

				<category android:name="android.intent.category.LAUNCHER"/>
			</intent-filter>
		</activity>
	</application>

</manifest>


text:
package main

var dropletAggregationSpec = map[string][]string{
	"sonar_cpu": {"cpu"},
}

var dbaasAggregationSpec = map[string][]string{

	"postgresql_pg_stat_user_tables_idx_scan":      {"table_name"},
	"postgresql_pg_stat_user_tables_n_tup_ins":     {"table_name"},
	"postgresql_pg_stat_user_tables_n_tup_upd":     {"table_name"},
	"postgresql_pg_stat_user_tables_seq_scan":      {"table_name"},
	"postgresql_pg_stat_user_tables_n_tup_del":     {"table_name"},
	"postgresql_pg_stat_user_tables_idx_tup_fetch": {"table_name"},
	"postgresql_pg_stat_user_tables_seq_tup_read":  {"table_name"},

	"mysql_perf_schema_table_io_waits_total_fetch":          {"name"},
	"mysql_perf_schema_table_io_waits_total_update":         {"name"},
	"mysql_perf_schema_table_io_waits_total_delete":         {"name"},
	"mysql_perf_schema_table_io_waits_total_insert":         {"name"},
	"mysql_perf_schema_table_io_waits_seconds_total_fetch":  {"name"},
	"mysql_perf_schema_table_io_waits_seconds_total_update": {"name"},
	"mysql_perf_schema_table_io_waits_seconds_total_delete": {"name"},
	"mysql_perf_schema_table_io_waits_seconds_total_insert": {"name"},

	"mysql_threads_connected": {"validate_password_dictionary_file_last_parsed"},
	"mysql_threads_created":   {"validate_password_dictionary_file_last_parsed"},
	"mysql_threads_running":   {"validate_password_dictionary_file_last_parsed"},

	"mysql_handler_read_first":    {"innodb_buffer_pool_load_status", "innodb_buffer_pool_dump_status"},
	"mysql_handler_read_key":      {"innodb_buffer_pool_load_status", "innodb_buffer_pool_dump_status"},
	"mysql_handler_read_last":     {"innodb_buffer_pool_load_status", "innodb_buffer_pool_dump_status"},
	"mysql_handler_read_next":     {"innodb_buffer_pool_load_status", "innodb_buffer_pool_dump_status"},
	"mysql_handler_read_prev":     {"innodb_buffer_pool_load_status", "innodb_buffer_pool_dump_status"},
	"mysql_handler_read_rnd":      {"innodb_buffer_pool_load_status", "innodb_buffer_pool_dump_status"},
	"mysql_handler_read_rnd_next": {"innodb_buffer_pool_load_status", "innodb_buffer_pool_dump_status"},

	"kafka_log_log_size_value":                                        {"partition"},
	"kafka_server_brokertopicmetrics_bytesinpersec_count":             {"topic"},
	"kafka_server_brokertopicmetrics_bytesoutpersec_count":            {"topic"},
	"kafka_server_brokertopicmetrics_messagesinpersec_count":          {"topic"},
	"kafka_server_brokertopicmetrics_replicationbytesinpersec_count":  {"topic"},
	"kafka_server_brokertopicmetrics_replicationbytesoutpersec_count": {"topic"},
}

var k8sAggregationSpec = map[string][]string{

	"kube_deployment_spec_replicas":               {"deployment", "namespace"},
	"kube_deployment_status_replicas_available":   {"deployment", "namespace"},
	"kube_deployment_status_replicas_unavailable": {"deployment", "namespace"},

	"kube_daemonset_status_desired_number_scheduled": {"daemonset", "namespace"},
	"kube_daemonset_status_number_available":         {"daemonset", "namespace"},
	"kube_daemonset_status_number_unavailable":       {"daemonset", "namespace"},

	"kube_statefulset_replicas":              {"statefulset", "namespace"},
	"kube_statefulset_status_replicas_ready": {"statefulset", "namespace"},
}


text:
=====================
salt.cloud.clouds.gce
=====================

.. automodule:: salt.cloud.clouds.gce
    :members:


text:
{% extends "hqwebapp/base_section.html" %}
{% load i18n %}
{% load hq_shared_tags %}
{% load crispy_forms_tags %}

{% requirejs_main 'integration/js/biometric' %}

{% block page_content %}
  {% initial_page_data 'simprintsFormData' simprints_form.initial_data %}

        {% trans 'Simprints Integration' %}

      {% crispy simprints_form %}

{% endblock %}


text:
.. _about-contributing:
.. highlight:: shell

======================
Contributing to Waffle
======================

Waffle is pretty simple to hack, and has a decent test suite! Here's how
to patch Waffle, add tests, run them, and contribute changes.

**Please** `open a new issue`_ to discuss a new feature before beginning
work on it. Not all suggestions are accepted. The :ref:`Goals
<about-goals>` may help guide which features are likely to be accepted.

Set Up
======

Setting up an environment is easy! You'll want ``virtualenv`` and
``pip``, then just create a new virtual environment and install the
requirements::

    $ mkvirtualenv waffle
    $ pip install -r requirements.txt

Done!

Writing Patches
===============

Fork_ Waffle and create a new branch off master for your patch. Run the
tests often::

    $ ./run.sh test

Try to keep each branch to a single feature or bugfix.

.. note::

    To update branches, please **rebase** onto master, do not merge
    master into your branch.

Submitting Patches
==================

Open a pull request on GitHub!

Before a pull request gets merged, it should be **rebased** onto master
and squashed into a minimal set of commits. Each commit should include
the necessary code, test, and documentation changes for a single "piece"
of functionality.

To be mergeable, patches must:

- be rebased onto the latest master,
- be automatically mergeable,
- not break existing tests,
- not change existing tests without a *very* good reason,
- add tests for new code (bug fixes should include regression tests, new
  features should have relevant tests),
- not introduce any new flake8_ errors (run ``./run.sh lint``),
- document any new features, and
- have a `good commit message`_.

Regressions tests should fail without the rest of the patch and pass
with it.

.. _open a new issue: https://github.com/django-waffle/django-waffle/issues/new
.. _Fork: https://github.com/django-waffle/django-waffle/fork
.. _flake8: https://pypi.python.org/pypi/flake8
.. _good commit message: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html


text:
<?php

namespace PhpParser\Node\Stmt;

use PhpParser\Node;
use PhpParser\Error;

class UseUse extends Node\Stmt
{
    /** @var Node\Name Namespace, class, function or constant to alias */
    public $name;
    /** @var string Alias */
    public $alias;

    /**
     * Constructs an alias (use) node.
     *
     * @param Node\Name   $name       Namespace/Class to alias
     * @param null|string $alias      Alias
     * @param array       $attributes Additional attributes
     */
    public function __construct(Node\Name $name, $alias = null, array $attributes = array()) {
        if (null === $alias) {
            $alias = $name->getLast();
        }

        if ('self' == $alias || 'parent' == $alias) {
            throw new Error(sprintf(
                'Cannot use %s as %s because \'%2$s\' is a special class name',
                $name, $alias
            ));
        }

        parent::__construct(null, $attributes);
        $this->name = $name;
        $this->alias = $alias;
    }

    public function getSubNodeNames() {
        return array('name', 'alias');
    }
}


text:
const express = require('express');
const router = express.Router();

const co = require('co');
const OSS = require('ali-oss');

const AliOssConfig = require('../../config/aliOss.json');
const crypto = require('crypto');
const client = new OSS(AliOssConfig);

router.get("/*", function (req, res, next) {
	req.session.user ? console.log(req.session.user.username) : console.log("用户未登录");
	next();
// 	if (req.session.user){
// 		next();
// 	}else{
// 		res.send({
// 			message:"当前需要登录"
// 		})
// 	}
});
router.get(["/files", "/files/:dir"], function (req, res) {
	var dir = req.params.dir;
	dir = dir ? dir + "/" : undefined;
	co(function*() {
		const result = yield client.list({
			prefix: dir,
			delimiter: '/'
		});
		var dirFiles = result.objects,
			dirFolds = result.prefixes;

		res.send({
			dirFiles: dirFiles ? dirFiles.filter(function (f) {
				return f.name !== dir;
			}) : [],
			dirFolds: dirFolds ? dirFolds : []
		});
	}).catch(function (err) {
		console.log(err);
	});
});
router.post("/signatureUrl", function (req, res) {
	const fileName = req.body.name;
	const url = client.signatureUrl(fileName);
	res.send({
		url: url
	})
});
router.get("/signatureUrl/:filename", function (req, res) {
	const filename = req.params.filename;
	const url = client.signatureUrl(filename);
	res.send({
		url: url
	})
});
router.delete("/*", function (req, res) {
	const filename = req.body.name;
	co(function*() {
		const result = yield client.delete(filename);
		res.send({
			status: "ok",
			filename: filename,
			result: result
		})
	}).catch(function (err) {
		res.send({
			status: "fail",
			err: err
		})
	});
});
// router.delete("/:filename", function (req, res) {
// 	const filename = req.params.filename;
// 	co(function*() {
// 		const result = yield client.delete(filename);
// 		res.send({
// 			status: "ok",
// 			filename: filename,
// 			result: result
// 		})
// 	}).catch(function (err) {
// 		res.send({
// 			status: "fail",
// 			err: err
// 		})
// 	});
// });
/**
 * 获取 oss 临时上传权限, 根据 oss 要求的参数伪装生成参数
 */
router.get("/signatureUpload", function (req, res) {
	const current = (new Date()).getTime(),
		//30 分钟的有效时间
		expires = current + 1000 * 60 * 30,
		policy = {
			expiration: new Date(expires).toISOString(),
			conditions: [
				["content-length-range", 0, 1048576000]
			]
		},
		// policy base64编码
		policyBase64 = new Buffer(JSON.stringify(policy)).toString("base64"),
		// sha1 加密, 秘钥 为 AliOssConfig.accessKeySecret, 加密 policyBase64 以base64输出
		signature = crypto.createHmac('sha1', AliOssConfig.accessKeySecret).update(policyBase64).digest('base64');

	res.send({
		accessid: AliOssConfig.accessKeyId,
		host: "http://" + AliOssConfig.bucket + "." + AliOssConfig.region + ".aliyuncs.com",
		policy: policyBase64,
		signature: signature,
		expire: expires
	});
});
router.post("/createDir", function (req, res) {
	var foldName = req.body.foldName;
	if (foldName[foldName.length - 1] !== "/") {
		foldName = foldName + "/";
	}
	co(function*() {
		var result = yield client.put(foldName, new Buffer(''), {
			meta: {
				type: 'dir'
			}
		});
		res.send({
			result,
			status: 'ok'
		});
	}).catch(function (err) {
		res.send({
			err: err
		})
	});

});
module.exports = router;


text:
Module Example

    Sub Main()
        ' High-level interface example
        Dim Tbp As Double
        Tbp = CoolProp.CoolProp.PropsSI("T", "P", 101325, "Q", 0, "Water")
        Console.Write(Tbp)
        Console.Write(vbCrLf)

        ' Low-level interface example
        Dim Water As CoolProp.AbstractState
        Water = CoolProp.AbstractState.factory("HEOS", "Water")
        Water.update(CoolProp.input_pairs.PQ_INPUTS, 101325, 0)
        Console.Write(Water.T())
        Console.Write(vbCrLf)

    End Sub

End Module