Re: svn commit: r1331110 - in /httpd/httpd/trunk: ./ modules/cache/ modules/dav/fs/ modules/filters/ modules/generators/ modules/loggers/ modules/mappers/ modules/slotmem/ support/

2013-01-08 Thread Joe Orton
On Thu, Apr 26, 2012 at 09:44:52PM -, s...@apache.org wrote:
 Author: sf
 Date: Thu Apr 26 21:44:51 2012
 New Revision: 1331110
 
 URL: http://svn.apache.org/viewvc?rev=1331110view=rev
 Log:
 Replace use of apr_file_write() with apr_file_write_full() to prevent
 incomplete writes.
 
 Add comments in some places where error handling/logging is missing.

I just saw this in STATUS.

I think this isn't right for mod_log_*, which should use a single 
write() call per log line, and fail in all error case.  Using 
_write_full() means we lose the guarantee of an atomic write.

Regards, Joe


Re: [Discuss] mod_lua and database connectivity

2013-01-08 Thread Daniel Gruno
On 01/06/2013 07:21 PM, Daniel Gruno wrote:
 On 01/06/2013 04:23 PM, Stefan Fritsch wrote:
 On Sun, 6 Jan 2013, Daniel Gruno wrote:
 -- Regular prepared statement creation:
 local prepped, err = db:prepare(SELECT * FROM `tbl` WHERE `id` = %s)
 if not err then
 local result, err = prepped(foobar) -- insert foobar as id
 ...
 end
 
 -- Fetch from DBDPrepareSQL:
 local prepped, err = db:prepared(someTag)
 if not err then
 local result, err = prepped(foobar) -- insert foobar as id
 ...
 end
 

One last change before I commit the code; prepared statements now have
two functions identical to the database object; select and query. These
were formerly known as query and run in the db object, but I have
renamed them to comply with the naming conventions of apr_dbd, thus
'query' is for running a command and fetching the no. of rows affected,
and 'select' is for...selecting :)

So, prepared statements are now run as follows:

-- select stuff
local prepared, err = db:prepare(SELECT * FROM `tbl` WHERE `age`  %u)
if not err then
local result, err = prepared:select(1234)

end

-- run stuff
local prepared, err = db:prepare(DELETE FROM `tbl` WHERE `age`  %u)
if not err then
local result, err = prepared:query(1234)

end

With regards,
Daniel.


Re: Balancer persist and inherit stuff in trunk

2013-01-08 Thread Jim Jagielski
re: increased performance. True enough, but we should
also be aware that the vast majority of people are still
running 2.2.x and that httpd is still seen as a slow,
bloated monster compared to nginx, which is gradually
being seen as the web-server for the web.

On Jan 7, 2013, at 5:36 PM, Stefan Fritsch s...@sfritsch.de wrote:

 On Sunday 06 January 2013, Jim Jagielski wrote:
 We could, but it's not my personal pref as RM...
 After all, ApacheCon will be here before we know
 it :/
 
 That's probably true ;)
 
 FWIW, I see the this dynamic nature of 2.4 as much
 as a killer feature as the increased performance
 as related to comparisons between httpd and other
 web-servers out there, including the fanboys latest
 flavor. Hence my desire to try to have this in
 asap, so I can re-dive into the optimized event/simple-
 MPM hybrid I was working on, which itself I hope to
 have done by ACNA2013.
 
 BTW, I don't believe the increased performance in 2.4 should be 
 overrated. It gives some nice improvements with some workloads, but 
 there are still plenty of cases where scalability remains bad (e.g. 
 ssl or long-lasting proxy-requests).
 



Re: Balancer persist and inherit stuff in trunk

2013-01-08 Thread Jim Jagielski
+1 for both being reset...

On Jan 7, 2013, at 4:40 AM, Rainer Jung rainer.j...@kippdata.de wrote:

 On 06.01.2013 17:48, Jim Jagielski wrote:
 I had thought that I has responded to that orig
 email that both below issues where by design
 but could be adjusted if need be or desired.
 
 I have no opinions either way, but to be Used seems
 more session based and Elected is more long-term
 statistical.
 
 Hmmm, but the Used field should give information about shm slots
 occupied by configured balancers. Isn't the info (=0) wrong after a restart?
 
 Concerning the long term statistical values I'm undecided like you, but
 I think we should handle them in a consistent way, so traffic and
 elected should either be both persisted or both reset.
 
 Regards,
 
 Rainer
 
 On Jan 5, 2013, at 1:41 PM, Rainer Jung rainer.j...@kippdata.de wrote:
 
 On 04.01.2013 19:48, Jim Jagielski wrote:
 Have people had a chance to test, review and try the balancer
 persist and inheritance stuff in trunk? I want to make
 sure that we have some level of verification and agreement
 there before I work on the backports for 2.4 ;)
 
 I didn't see any changes with respect to two of my original comments:
 
 The Used counters (number of shared mem slots) in balancer manager
 drops to 0 after restart/reboot´with persist on. This seems strange.
 Not that Used does *not* have anything to do with request counting.
 
 Second the Elected counter is persisted but e.g. the traffic counter's
 not. This seems somewhat inconsistent. I have no strong opinion whether
 to persist statistics or not, but we might want to behave consistently.
 
 I did not observe any functional changes after my Mail from Dec. 14, right?
 
 Regards,
 
 Rainer
 



Re: Balancer persist and inherit stuff in trunk

2013-01-08 Thread Jim Jagielski
Hold on a tic... let me go thru my notes. I seem to recall
an issue I hit.

On Jan 8, 2013, at 9:28 AM, Jim Jagielski j...@jagunet.com wrote:

 +1 for both being reset...
 
 On Jan 7, 2013, at 4:40 AM, Rainer Jung rainer.j...@kippdata.de wrote:
 
 On 06.01.2013 17:48, Jim Jagielski wrote:
 I had thought that I has responded to that orig
 email that both below issues where by design
 but could be adjusted if need be or desired.
 
 I have no opinions either way, but to be Used seems
 more session based and Elected is more long-term
 statistical.
 
 Hmmm, but the Used field should give information about shm slots
 occupied by configured balancers. Isn't the info (=0) wrong after a restart?
 
 Concerning the long term statistical values I'm undecided like you, but
 I think we should handle them in a consistent way, so traffic and
 elected should either be both persisted or both reset.
 
 Regards,
 
 Rainer
 
 On Jan 5, 2013, at 1:41 PM, Rainer Jung rainer.j...@kippdata.de wrote:
 
 On 04.01.2013 19:48, Jim Jagielski wrote:
 Have people had a chance to test, review and try the balancer
 persist and inheritance stuff in trunk? I want to make
 sure that we have some level of verification and agreement
 there before I work on the backports for 2.4 ;)
 
 I didn't see any changes with respect to two of my original comments:
 
 The Used counters (number of shared mem slots) in balancer manager
 drops to 0 after restart/reboot´with persist on. This seems strange.
 Not that Used does *not* have anything to do with request counting.
 
 Second the Elected counter is persisted but e.g. the traffic counter's
 not. This seems somewhat inconsistent. I have no strong opinion whether
 to persist statistics or not, but we might want to behave consistently.
 
 I did not observe any functional changes after my Mail from Dec. 14, right?
 
 Regards,
 
 Rainer
 
 



Re: Balancer persist and inherit stuff in trunk

2013-01-08 Thread Jim Jagielski
Yeppers...

actually, transferred and read *are* persisted, it's just
that the bytraffic lbmethod is smart enough to know that
when the config is changed, those counters need to
be reset and, by default, a restart is a change.
Since elected is never used for any sort of lbmethod,
it never is reset and so the persist holds.

So the idea is that lbmethods should reset any potential
persisted values iff it makes sense for that lbmethod.
bytraffic resets transferred/read but byrequests doesn't,
for example.

On Jan 8, 2013, at 9:49 AM, Jim Jagielski j...@jagunet.com wrote:

 Hold on a tic... let me go thru my notes. I seem to recall
 an issue I hit.
 
 On Jan 8, 2013, at 9:28 AM, Jim Jagielski j...@jagunet.com wrote:
 
 +1 for both being reset...
 
 On Jan 7, 2013, at 4:40 AM, Rainer Jung rainer.j...@kippdata.de wrote:
 
 On 06.01.2013 17:48, Jim Jagielski wrote:
 I had thought that I has responded to that orig
 email that both below issues where by design
 but could be adjusted if need be or desired.
 
 I have no opinions either way, but to be Used seems
 more session based and Elected is more long-term
 statistical.
 
 Hmmm, but the Used field should give information about shm slots
 occupied by configured balancers. Isn't the info (=0) wrong after a restart?
 
 Concerning the long term statistical values I'm undecided like you, but
 I think we should handle them in a consistent way, so traffic and
 elected should either be both persisted or both reset.
 
 Regards,
 
 Rainer
 
 On Jan 5, 2013, at 1:41 PM, Rainer Jung rainer.j...@kippdata.de wrote:
 
 On 04.01.2013 19:48, Jim Jagielski wrote:
 Have people had a chance to test, review and try the balancer
 persist and inheritance stuff in trunk? I want to make
 sure that we have some level of verification and agreement
 there before I work on the backports for 2.4 ;)
 
 I didn't see any changes with respect to two of my original comments:
 
 The Used counters (number of shared mem slots) in balancer manager
 drops to 0 after restart/reboot´with persist on. This seems strange.
 Not that Used does *not* have anything to do with request counting.
 
 Second the Elected counter is persisted but e.g. the traffic counter's
 not. This seems somewhat inconsistent. I have no strong opinion whether
 to persist statistics or not, but we might want to behave consistently.
 
 I did not observe any functional changes after my Mail from Dec. 14, 
 right?
 
 Regards,
 
 Rainer
 
 
 



Re: Balancer persist and inherit stuff in trunk

2013-01-08 Thread Jim Jagielski
Rainer, does the below address your concern and make
it OK that the current behavior acts the way it does
and we're OK to keep it that way.

On Jan 8, 2013, at 10:25 AM, Jim Jagielski j...@jagunet.com wrote:

 Yeppers...
 
 actually, transferred and read *are* persisted, it's just
 that the bytraffic lbmethod is smart enough to know that
 when the config is changed, those counters need to
 be reset and, by default, a restart is a change.
 Since elected is never used for any sort of lbmethod,
 it never is reset and so the persist holds.
 
 So the idea is that lbmethods should reset any potential
 persisted values iff it makes sense for that lbmethod.
 bytraffic resets transferred/read but byrequests doesn't,
 for example.
 
 On Jan 8, 2013, at 9:49 AM, Jim Jagielski j...@jagunet.com wrote:
 
 Hold on a tic... let me go thru my notes. I seem to recall
 an issue I hit.
 
 On Jan 8, 2013, at 9:28 AM, Jim Jagielski j...@jagunet.com wrote:
 
 +1 for both being reset...
 
 On Jan 7, 2013, at 4:40 AM, Rainer Jung rainer.j...@kippdata.de wrote:
 
 On 06.01.2013 17:48, Jim Jagielski wrote:
 I had thought that I has responded to that orig
 email that both below issues where by design
 but could be adjusted if need be or desired.
 
 I have no opinions either way, but to be Used seems
 more session based and Elected is more long-term
 statistical.
 
 Hmmm, but the Used field should give information about shm slots
 occupied by configured balancers. Isn't the info (=0) wrong after a 
 restart?
 
 Concerning the long term statistical values I'm undecided like you, but
 I think we should handle them in a consistent way, so traffic and
 elected should either be both persisted or both reset.
 
 Regards,
 
 Rainer
 
 On Jan 5, 2013, at 1:41 PM, Rainer Jung rainer.j...@kippdata.de wrote:
 
 On 04.01.2013 19:48, Jim Jagielski wrote:
 Have people had a chance to test, review and try the balancer
 persist and inheritance stuff in trunk? I want to make
 sure that we have some level of verification and agreement
 there before I work on the backports for 2.4 ;)
 
 I didn't see any changes with respect to two of my original comments:
 
 The Used counters (number of shared mem slots) in balancer manager
 drops to 0 after restart/reboot´with persist on. This seems strange.
 Not that Used does *not* have anything to do with request counting.
 
 Second the Elected counter is persisted but e.g. the traffic counter's
 not. This seems somewhat inconsistent. I have no strong opinion whether
 to persist statistics or not, but we might want to behave consistently.
 
 I did not observe any functional changes after my Mail from Dec. 14, 
 right?
 
 Regards,
 
 Rainer
 
 
 
 



Re: thread-safety of time conversion caches in util_time.c and mod_log_config.c

2013-01-08 Thread Daniel Lescohier
It looks like apr_atomic is not in good-enough shape to be used for
lock-free algorithms.  It's probably good enough for the use-cases that the
event mpm uses it for, because the event mpm is not using it for protecting
memory besides the counters it's atomically changing.  However, the time
caches would use the cache key to protect other memory (the cache value),
so apr_atomic is not good enough, because it's inconsistent on the
different platforms with respect to memory barriers.

For example, with x86, the add32 and cas32 functions act as a full memory
barrier on all memory.  However, for powerpc, the add32 and cas32 only acts
as a memory barrier on the individual item being changed, it doesn't act as
a memory barrier on all memory.  One would have to add lightweight sync
assembler instructions to the add32 and cas32 function implementations for
powerpc if you want the same semantics as x86.

The problem is that the apr_atomic API is not explicit with the memory
ordering semantics.  I agree with you that in the future the apr_atomic API
should be changed to be more like the C11 atomic API, which allows explicit
choice of memory ordering.

But that leaves us with the problem of the current time caching code, which
is not thread-safe.  We should fix it using the existing APR APIs, and not
use the apr_atomic API which is broken for this use-case.

I found that there is a lock-free method available to us with the current
APR API.  We can use apr_thread_mutex_trylock.  In glibc, that just
attempts to cmpxchg the userspace futex, and if it fails, it doesn't do a
futex system call and a wait on the caller, so it's lock free.  On Windows,
TryEnterCriticalSection probably works the same way.

So, the pseudo-code would be something like:

For reading from cache:

apr_uint32_t key = cache_element-key;
/* Above is done speculatively */
if (seconds == key  seconds != 0) {
/* seconds == 0 may mean cache is uninitialized, so don't use cache
*/
*xt = cache_element-xt;
/* After copying xt, make sure cache_element was not marked invalid
 * by another thread beginning an update, and that cache_element
 * really contained data for our second. */
if (apr_thread_mutex_trylock(cache_element-mutex) == APR_SUCCESS) {
key = cache_element-key;
apr_thread_mutex_unlock(cache_element-mutex);
if (key == seconds) {
xt-tm_usec = (int)apr_time_usec(t);
return APR_SUCCESS;
}
}
}
/* calculate the value if reached here */

Write to cache code:

if (apr_thread_mutex_trylock(cache_element-mutex) == APR_SUCCESS)
{  /* We won the race to update this cache_element. */
cache_element-key = ~seconds;
/* Above marks cache_element as invalid by using ~seconds,
 * for the speculative reads not using the mutex. */
cache_element-xt = *xt;
/* Finished copying, now update key with our key */
cache_element-key = seconds;
apr_thread_mutex_unlock(cache_element-mutex);
}

The above is lock-free, because process scheduling decisions by the OS
won't cause the current thread to block, it'll keep on doing work without
blocking as long as this thread is scheduled.  It would be fast, though
perhaps not quite as fast than if we had an atomic api we could use
effectively.  With an atomic API, the read-from-time-cache code would only
be reading from cache-lines, not writing to cache-lines with the futex's
cmpxchg instruction.  You might also be able to use a lighter-weight memory
barrier.  But the mutex is lock-free and fast, and it's something that'd
work with today's APIs; and the existing code in production is not correct.

BTW, I looked at rwlock_trylock, and that isn't lock-free in glibc, because
the readers/writers count variables are protected with a low-level lock
futex that is acquired with lll_lock, not lll_trylock.  So, if a thread
acquires the low-level lock, but is unscheduled by the OS before it
finishes updating the reader/writers count variables and unlocks the
low-level lock, that would block other threads from acquiring the
low-level lock, and other threads would block before being able to access
the readers/writers count variables.  If it had used lll_trylock instead, I
think it would've been lock-free.  However, I don't think rwlock would give
us any particular advantage than a regular mutex for the above algorithm.

So using the simpler mutex is better and is lock-free.  I think the
important part is to have a lock-free algorithm: if we lose a little bit of
performance by not being able to use the lightest lock-free algorithm, I
think that is OK.

On Mon, Jan 7, 2013 at 5:50 PM, Stefan Fritsch s...@sfritsch.de wrote:

 On Sunday 06 January 2013, Daniel Lescohier wrote:
  I'm not sure we should include memory barriers inside the
  apr_atomic_read32 and apr_atomic_set32 functions, because 

Re: thread-safety of time conversion caches in util_time.c and mod_log_config.c

2013-01-08 Thread Daniel Lescohier
Some timing tests:

 gcc -I/usr/include/apr-1 -lrt -lapr-1 -lpthread test.c
 ./a.out
apr_time_exp_lt: 108 nanosecs per call
localtime_r: 85 nanosecs per call
apr_time_exp_gmt: 59 nanosecs per call
gmtime_r: 35 nanosecs per call
pthread_mutex_trylock/unlock/read cache: 19 nanosecs per call
lfence/read cache: 8 nanosecs per call
read cache: 4 nanosecs per call
 cat test.c
#include time.h
#include stdio.h
#include assert.h
#include apr_time.h
#include pthread.h


int main (int argc, char *argv[]) {
struct timespec old, new;
struct tm tmv;
int i, iterations=1000;
long nanosecs;
#define CALC_NS(new, old) ((new.tv_sec - old.tv_sec)*10 +
new.tv_nsec - old.tv_nsec)
apr_time_t t = apr_time_now();
apr_time_exp_t xt;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
unsigned int seconds=1;
typedef struct { char s[44]; unsigned int key;} data_t;
static volatile data_t cache_data;
data_t my_copy;

cache_data.key = 1;

assert(clock_gettime(CLOCK_MONOTONIC_RAW, old)==0);
for (i=0; i  iterations; ++i) {
apr_time_exp_lt(xt, t);
}
assert(clock_gettime(CLOCK_MONOTONIC_RAW, new)==0);
nanosecs = CALC_NS(new, old);
printf(apr_time_exp_lt: %d nanosecs per call\n, nanosecs/iterations);

assert(clock_gettime(CLOCK_MONOTONIC_RAW, old)==0);
for (i=0; i  iterations; ++i) {
localtime_r(old.tv_sec, tmv);
}
assert(clock_gettime(CLOCK_MONOTONIC_RAW, new)==0);
nanosecs = CALC_NS(new, old);
printf(localtime_r: %d nanosecs per call\n, nanosecs/iterations);

assert(clock_gettime(CLOCK_MONOTONIC_RAW, old)==0);
for (i=0; i  iterations; ++i) {
apr_time_exp_gmt(xt, t);
}
assert(clock_gettime(CLOCK_MONOTONIC_RAW, new)==0);
nanosecs = CALC_NS(new, old);
printf(apr_time_exp_gmt: %d nanosecs per call\n, nanosecs/iterations);

assert(clock_gettime(CLOCK_MONOTONIC_RAW, old)==0);
for (i=0; i  iterations; ++i) {
gmtime_r(old.tv_sec, tmv);
}
assert(clock_gettime(CLOCK_MONOTONIC_RAW, new)==0);
nanosecs = CALC_NS(new, old);
printf(gmtime_r: %d nanosecs per call\n, nanosecs/iterations);

assert(clock_gettime(CLOCK_MONOTONIC_RAW, old)==0);
for (i=0; i  iterations; ++i) {
int key = cache_data.key;
if (seconds==key  key!=0) {
my_copy = cache_data;
if (pthread_mutex_trylock(mutex)==0) {
key = cache_data.key;
pthread_mutex_unlock(mutex);
}
}
}
assert(clock_gettime(CLOCK_MONOTONIC_RAW, new)==0);
nanosecs = CALC_NS(new, old);
printf(pthread_mutex_trylock/unlock/read cache: %d nanosecs per
call\n, nanosecs/iterations);

assert(clock_gettime(CLOCK_MONOTONIC_RAW, old)==0);
for (i=0; i  iterations; ++i) {
int key = cache_data.key;
if (seconds==key  key!=0) {
my_copy = cache_data;
asm volatile(lfence:::memory);
key = cache_data.key;
}
}
assert(clock_gettime(CLOCK_MONOTONIC_RAW, new)==0);
nanosecs = CALC_NS(new, old);
printf(lfence/read cache: %d nanosecs per call\n,
nanosecs/iterations);

assert(clock_gettime(CLOCK_MONOTONIC_RAW, old)==0);
for (i=0; i  iterations; ++i) {
int key = cache_data.key;
if (seconds==key  key!=0) {
my_copy = cache_data;
key = cache_data.key;
}
}
assert(clock_gettime(CLOCK_MONOTONIC_RAW, new)==0);
nanosecs = CALC_NS(new, old);
printf(read cache: %d nanosecs per call\n, nanosecs/iterations);
}


On Tue, Jan 8, 2013 at 1:50 PM, Daniel Lescohier
daniel.lescoh...@cbsi.comwrote:

 It looks like apr_atomic is not in good-enough shape to be used for
 lock-free algorithms.  It's probably good enough for the use-cases that the
 event mpm uses it for, because the event mpm is not using it for protecting
 memory besides the counters it's atomically changing.  However, the time
 caches would use the cache key to protect other memory (the cache value),
 so apr_atomic is not good enough, because it's inconsistent on the
 different platforms with respect to memory barriers.

 For example, with x86, the add32 and cas32 functions act as a full memory
 barrier on all memory.  However, for powerpc, the add32 and cas32 only acts
 as a memory barrier on the individual item being changed, it doesn't act as
 a memory barrier on all memory.  One would have to add lightweight sync
 assembler instructions to the add32 and cas32 function implementations for
 powerpc if you want the same semantics as x86.

 The problem is that the apr_atomic API is not explicit with the memory
 ordering semantics.  I agree with you that in the future the apr_atomic API
 should be changed to be more like the C11 atomic API, which allows explicit
 choice of memory ordering.

 But that leaves us with the problem of the current time caching code,
 which is not thread-safe.  We should fix it using the existing APR APIs,
 and not use the 

Re: svn commit: r1430590 - /httpd/httpd/branches/2.4.x/STATUS

2013-01-08 Thread Daniel Gruno
On 01/08/2013 11:40 PM, j...@apache.org wrote:
 Author: jim
 Date: Tue Jan  8 22:40:29 2013
 New Revision: 1430590
 
 URL: http://svn.apache.org/viewvc?rev=1430590view=rev
 Log:
 BalancerInherit proposal
 
 Modified:
 httpd/httpd/branches/2.4.x/STATUS
 
 Modified: httpd/httpd/branches/2.4.x/STATUS
 URL: 
 http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/STATUS?rev=1430590r1=1430589r2=1430590view=diff
 ==
 --- httpd/httpd/branches/2.4.x/STATUS (original)
 +++ httpd/httpd/branches/2.4.x/STATUS Tue Jan  8 22:40:29 2013
 @@ -176,6 +176,20 @@ PATCHES PROPOSED TO BACKPORT FROM TRUNK:
   2.4.x patch: trunk patch works + CHANGES to be added
   +1: jailletc36, jim
  
 +   * mod_proxy: Allow balancers to be server-specific, as they should have
 + been. Inheritance causes too many behind-the-scene interactions
 + to be reliable in a dynamic environ. We maintain the old-default
 + of inheritance.
 + trunk patch: http://svn.apache.org/viewvc?view=revisionrevision=1387603
 +  http://svn.apache.org/viewvc?view=revisionrevision=1388029
 +  http://svn.apache.org/viewvc?view=revisionrevision=1420124
 +  http://svn.apache.org/viewvc?view=revisionrevision=1421288
 +  http://svn.apache.org/viewvc?view=revisionrevision=1421912
 +  http://svn.apache.org/viewvc?view=revisionrevision=1422943
 +  http://svn.apache.org/viewvc?view=revisionrevision=1422980
 +  http://svn.apache.org/viewvc?view=revisionrevision=1430575
 + 2.4.x patch: 
 http://people.apache.org/~jim/patches/proxypassinherit2.patch
 + +1: jim
  
  
  A list of further possible backports can be found at:
 
 
Did you mean
http://people.apache.org/~jim/patches/proxypassinherit.patch (without
the '2') ?

With regards,
Daniel.