1 /* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /*
3  *     Copyright 2013 Couchbase, Inc.
4  *
5  *   Licensed under the Apache License, Version 2.0 (the "License");
6  *   you may not use this file except in compliance with the License.
7  *   You may obtain a copy of the License at
8  *
9  *       http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *   Unless required by applicable law or agreed to in writing, software
12  *   distributed under the License is distributed on an "AS IS" BASIS,
13  *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *   See the License for the specific language governing permissions and
15  *   limitations under the License.
16  */
17 
18 #include "pool.h"
19 
20 using namespace lcb;
21 using std::queue;
22 using std::vector;
23 
24 Pool::Pool(const lcb_create_st& options, size_t nitems) : initial_size(0)
25 {
26     pthread_mutex_init(&mutex, NULL);
27     pthread_cond_init(&cond, NULL);
28     for (size_t ii = 0; ii < nitems; ii++) {
29         lcb_t cur;
30         lcb_error_t err = lcb_create(&cur, &options);
31         if (err != LCB_SUCCESS) {
32             throw err;
33         }
34 
35         instances.push(cur);
fsm_page_contents(PG_FUNCTION_ARGS)36         all_instances.push_back(cur);
37         initial_size++;
38     }
39 }
40 
41 lcb_error_t
42 Pool::connect()
43 {
44     vector<lcb_t>::const_iterator ii = all_instances.begin();
45     for (;  ii != all_instances.end(); ii++) {
46         lcb_error_t err;
47         initialize(*ii);
48         if ((err = lcb_connect(*ii)) != LCB_SUCCESS) {
49             return err;
50         }
51         lcb_wait(*ii);
52         if ((err = lcb_get_bootstrap_status(*ii)) != LCB_SUCCESS) {
53             return err;
54         }
55     }
56     return LCB_SUCCESS;
57 }
58 
59 Pool::~Pool()
60 {
61     pthread_mutex_lock(&mutex);
62     while (instances.size() < initial_size) {
63         pthread_cond_wait(&cond, &mutex);
64     }
65     vector<lcb_t>::const_iterator ii = all_instances.begin();
66     for (; ii != all_instances.end(); ii++) {
67         lcb_destroy(*ii);
68     }
69     pthread_mutex_unlock(&mutex);
70     pthread_mutex_destroy(&mutex);
71     pthread_cond_destroy(&cond);
72 }
73 
74 lcb_t
75 Pool::pop()
76 {
77     lcb_t ret = NULL;
78 
79     // Need to lock the mutex to the pool structure itself
80     pthread_mutex_lock(&mutex);
81 
82     while (instances.empty()) {
83         pthread_cond_wait(&cond, &mutex);
84     }
85 
86     ret = instances.front();
87     instances.pop();
88     pthread_mutex_unlock(&mutex);
89 
90     // Note that the instance itself does not need a mutex as long as it is not
91     // used between multiple threads concurrently.
92     return ret;
93 }
94 
95 void
96 Pool::push(lcb_t instance)
97 {
98     pthread_mutex_lock(&mutex);
99     instances.push(instance);
100     pthread_cond_signal(&cond);
101     pthread_mutex_unlock(&mutex);
102 }
103