2 #include "libmemcached/memcached_pool.h"
5 struct memcached_pool_st
17 * Lock a the pthread mutex and handle error conditions. If we fail to
18 * lock the mutex there must be something really wrong and we cannot continue.
20 static void mutex_enter(pthread_mutex_t
*mutex
)
24 ret
= pthread_mutex_lock(mutex
);
25 while (ret
== -1 && errno
== EINTR
);
30 ** This means something is seriously wrong (deadlock or an internal
31 ** error in the posix library. Print out an error message and abort
34 fprintf(stderr
, "pthread_mutex_lock failed: %s\n", strerror(errno
));
41 * Unlock a the pthread mutex and handle error conditions.
42 * All errors except EINTR is fatal errors and will terminate the program
45 static void mutex_exit(pthread_mutex_t
*mutex
) {
48 ret
= pthread_mutex_unlock(mutex
);
49 while (ret
== -1 && errno
== EINTR
);
54 ** This means something is seriously wrong (deadlock or an internal
55 ** error in the posix library. Print out an error message and abort
58 fprintf(stderr
, "pthread_mutex_unlock %s\n", strerror(errno
));
65 * Grow the connection pool by creating a connection structure and clone the
66 * original memcached handle.
68 static int grow_pool(memcached_pool_st
* pool
) {
69 memcached_st
*obj
= calloc(1, sizeof(*obj
));
73 if (memcached_clone(obj
, pool
->master
) == NULL
)
79 pool
->mmc
[++pool
->firstfree
] = obj
;
85 memcached_pool_st
*memcached_pool_create(memcached_st
* mmc
, int initial
, int max
)
87 memcached_pool_st
* ret
= NULL
;
88 memcached_pool_st object
= { .mutex
= PTHREAD_MUTEX_INITIALIZER
,
89 .cond
= PTHREAD_COND_INITIALIZER
,
91 .mmc
= calloc(max
, sizeof(memcached_st
*)),
96 if (object
.mmc
!= NULL
)
98 ret
= calloc(1, sizeof(*ret
));
107 /* Try to create the initial size of the pool. An allocation failure at
108 * this time is not fatal..
110 for (int ii
=0; ii
< initial
; ++ii
)
111 if (grow_pool(ret
) == -1)
118 memcached_st
* memcached_pool_destroy(memcached_pool_st
* pool
)
120 memcached_st
*ret
= pool
->master
;
122 for (int ii
= 0; ii
<= pool
->firstfree
; ++ii
)
124 memcached_free(pool
->mmc
[ii
]);
126 pool
->mmc
[ii
] = NULL
;
129 pthread_mutex_destroy(&pool
->mutex
);
130 pthread_cond_destroy(&pool
->cond
);
137 memcached_st
* memcached_pool_pop(memcached_pool_st
* pool
, bool block
) {
138 memcached_st
*ret
= NULL
;
139 mutex_enter(&pool
->mutex
);
142 if (pool
->firstfree
> -1)
143 ret
= pool
->mmc
[pool
->firstfree
--];
144 else if (pool
->current_size
== pool
->size
)
148 mutex_exit(&pool
->mutex
);
152 if (pthread_cond_wait(&pool
->cond
, &pool
->mutex
) == -1)
155 ** This means something is seriously wrong (an internal error in the
156 ** posix library. Print out an error message and abort the program.
158 fprintf(stderr
, "pthread cond_wait %s\n", strerror(errno
));
163 else if (grow_pool(pool
) == -1)
165 mutex_exit(&pool
->mutex
);
171 mutex_exit(&pool
->mutex
);
175 void memcached_pool_push(memcached_pool_st
* pool
, memcached_st
*mmc
)
177 mutex_enter(&pool
->mutex
);
178 pool
->mmc
[++pool
->firstfree
] = mmc
;
180 if (pool
->firstfree
== 0 && pool
->current_size
== pool
->size
)
182 /* we might have people waiting for a connection.. wake them up :-) */
183 pthread_cond_broadcast(&pool
->cond
);
185 mutex_exit(&pool
->mutex
);