Mod_countm

Byron Young

Jan 7, 2006

An Apache 2 only DSO module serving link counting information via jpeg and png images. Direct support for Fedora Core 4 (i386) and FreeBSD 5.4-RELEASE (i386) distributions. Supports, at least, the major Multi-Processing Modules, separate virtual server databases and configurations, and per link background images. DB4 or MySQL database build options.

Chapter 1
Databases

1.1  Overview

For the purposes of this manual, a virtual server is defined to be the set of configuration directives applied via a <VirtualHost> directive, and the global server the set of all other directives.
For each counter, a database maintains per link information. Within each database, two sub databases are maintained; DB_COUNTER and DB_ACCESS. The DB_COUNTER sub-database maintains, for each link, a current count value and the default link settings. The DB_ACCESS sub-database maintains, for each link, a list of hosts that have accessed the link. Operations that alter the database may act upon one or both sub-databases.
The build time database may be one of MySQL>3.2.58 (www.mysql.com) or Berkeley DB4 (www.sleepycat.com).
The -with-bdb and the -with-mysql configure options select the mod_countm database. Setting both to 'no' is an error. A valid option adds the library to the linking process. For best results, specifically set one of -with-bdb or -with-mysql to 'no'.

1.2  DB4 Databases

Mod_countm DB4 database interfaces are designed to function within a single server machine installation. They will not function across multiple Apache servers installed and running on separate server machine installations. For a more detailed description, see Berkeley DB Reference Guide: Remote Filesystems.
The configuration option -with-bdb selects the Berkeley DB4 database.
The mod_countm Apache2 configuration directives CountmEnvironmentHome and CountmDB are used to describe a database (per server). The CountmDB file is created within the CountmEnvironmentHome directory. The two DB_ACCESS and DB_COUNTER sub-databases are created within the CountmDB file.
The linkname, when using DB4, is case sensitive. Domain names, in general, are not case sensitive. A future modification may changes this behavior. All linknames would be changed to lower case (strlower).
If the environment and database files do not exist, then mod_countm automatically creates them during the first request that uses them (not at server startup). On server shutdown (-SIGTERM), or server restart (-HUP), (assuming the environment lock count decreases to 0), the environment is deleted, but the database remains. If the environment exists and the lockfile does not exist (a condition that results from the server improperly shutdown, then the env.lock file manually deleted), recovery is run on the environment, the environment deleted, then recreated.
The countm utility may be used to create the database file.

1.3  DB4 Database File

       ¯Countm¯Enviro¯nmentHome/CountmDB
 DB_COUNTER:
  abcd  default values,count
  defg  default values,count
  lmno  default values,count
 DB_ACCESS:
  abcd  localhost
  abcd  www.hackedme.jerk
  abcd  www.knowitall.god
  defg  localhost
  hijk  localhost In this example, the CountmDB DB_COUNTER sub database contains 3 entries/links; abcd, defg, and lmno. DB_ACCESS contains 3 entries/links; abcd, defg, hijk. Note that DB_COUNTER contains entry/link lmno, but DB_ACCESS does not, and DB_ACCESS contains hijk, which DB_COUNTER does not. Links/entries abcd and defg which are in both DB_COUNTER and DB_ACCESS are typical of normal counter operation. They were entered into the counter database, and, have a list of associated hosts. However, links/entries hijk and lmno are not typical of normal counter operation. Link lmno probably was just entered into the database, and, either no hosts have accessed the links, or its access list was just deleted from DB_ACCESS. Link hijk was probably just deleted from DB_COUNTER, and the link/entry will be deleted soon from DB_ACCESS. Unmatched links/entries are perfectly acceptable, and considered normal by the internal counter update mechanism.

1.4  DB4 Database - Locking

The DB4 API defines a locking subsystem. For the most part, it is automatic, and certainly the Sleepycat documentation details its operations. As part of the locking subsystem, the application may define objects, with scope the database environment, to lock. The mod_countm module defines and obtains a lock object for each link (defined by the link= parameter) it is currently serving. This means that within an environment, no two threads_of_control (accessing a common environment) may access a links data, in any database defined within the environment, simultaneously.

1.5  DB4 Database - mod_countm environment lockfile

Additionally, mod_countm creates an environment lockfile within each environment (env.lck) that contains a count of the number of additional processes currently using the environment. Access to this file by mod_countm is subject to strict global locks. However, access to this file by other utilities that are aware of this file, is not controlled. The countm utility, for example, is aware of this environment lockfile. Providing the two do not attempt to access the file simultaneously, it will do its job. If the server crashes (shuts down incorrectly, or other reason) the env.lck file must be removed manually.
This lockfile is accessed whenever a process using the environment terminates or when a process opens/ creates the environment via a thread of control on first usage. For mod_countm, this is whenever the server shuts down, or restarts, or when a process thread of control uses the environment for the first time, or when a process using the environment terminates, either by exceeding MaxRequestsPerChild or by shutdown or by restart. If neither the Apache server is running or the countm utility is running, then this file should not exist. When a process closes an environment, and the lock count within the file is zero (0), that process attempts to remove the environment.

1.6  DB4 Databases - Fine Tuning

The database environments may be configured using a DB4 API DB_CONFIG file. See the Sleepycat DB4 documentation for proper usage. If this file exists when the environment is opened, it is read for configuration information.
Two compile time options, COUNTM_BDB_MAX_ENV and COUNTM_BDB_MAX_DB (countm_mod.h), determine the maximum number of BDB Environment Homes and BDB database files, respectively, that may be defined.

1.7  DB4 Databases - Utilities

The DB4 distribution contains numerous utilities to interact with the databases. Mod_countm does not implement any shared locks with these utilities. On Fedora Core systems, they may be listed with:
rpm -ql db4
rpm -ql db4-devel
rpm -ql db4-utils

The DB4 db_stat utility may be used to gather information about the environment.
The DB4 db_dump utility may be used to get a quick dump of the database file.
The DB4 db_recover utility may be used to recover stale locks. If DB4 locks are valid and the server crashes, they must be recovered. See the DB4 utility db_recover for more information.

1.8  MySQL Database

The -with-mysql configure option selects MySQL database.
The CountmMySQL mod_countm Apache2 configuration directive may be used to configure the connection parameters.
When using the MySQL database, the max allowable link parameter size is 255 bytes, and the maximum allowable hostname parameter size is 245 bytes. No check is made to enforce this. When HOSTNAMELOOKUPS ON, this has the potential to introduce inaccurate counts.
When using MySQL, all linkname searches are case insensitive. Domain names, in general, are case insensitive. A future modification may changes this behavior. All linknames would be changed to lower case (strlower).
The MySQL database implements the DB_COUNTER and DB_ACCESS sub-databases using tables.
Mod_countm access to the MySQL database tables is basic and each SELECT, DELETE, INSERT statement results in no more than one row of information being transmitted.

1.9  MySQL Database - Locking

For each query, both the DB_COUNTER and DB_ACCESS tables are locked. Because all tables are unlocked when a connection terminates, this should be automatic.

1.10  MySQL Database - Setting Up

Mod_countm will not create and/or delete the MySQL database and tables. See the countm utility for more information.
The CountmMySQL mod_countm Apache2 configuration directive uses a -db=name option to determine the database within MySQL to be used. Within that database, a DB_COUNTER and a DB_ACCESS table contain information about a specific link. The countm utility help option outputs the exact scripts it uses to create the tables.
The MySQL database administrator must grant permission for SELECT, INSERT, UPDATE, LOCK, DELETE, and CREATE operations to the configured MySQL user.
Note: When information here conflicts with the countm utilty info, use the countm utility information.
Ex:
CountmMySQL -user=bkyoung -host=waiter -db=COUNTM
(Administrator)
GRANT ALL ON COUNTM.* TO 'bkyoung'@'waiter.localzone.'
(As MySQL user ID bkyoung)
CREATE DATABASE COUNTM;
USE COUNTM;

CREATE TABLE DB_COUNTER (
link VARCHAR(255) NOT NULL PRIMARY KEY,
font TEXT NULL,
width INTEGER NULL,
point INTEGER NULL,
bgcolor TEXT NULL,
bgfile_type ENUM('jpeg', 'png') NULL,
text VARCHAR(7) NULL,
image ENUM('jpeg', 'png') NULL,
cnt BIGINT UNSIGNED NOT NULL,
random ENUM('true', 'false') NULL,
count ENUM('norm_inc', 'inc', 'inc_nopub', 'norm_dec', 'dec','dec_nopub') NULL,
atime DATE NOT NULL
);

CREATE TABLE DB_ACCESS (
link VARCHAR(255) NOT NULL,
host VARCHAR(245) NOT NULL,
PRIMARY KEY ( link, host));

Direct manipulation of the database, though possible, is not recommended. All information stored in the database is placed into the database with certain assumptions. Data within the database that does not meet these assumptions will force undefined runtime errors.

Chapter 2
Counter Usage

2.1  Common Errors

2.1.1  No link in Counter

Attempting to increment a link that has not be inserted into the database:
<IMG src="localhost/countm?link=linkname">

The returned image displays NoLink.
Solution:
Insert the counter into DB_COUNTER using
<IMG src="localhost/countm?link=linkname&reset=init:0">

The image will display "Cadd".
In general, avoid duplicate <IMG> tags in a html page. Browsers tend to optimize resource retrievals, and could receive the count image out of desired order.

2.1.2  insert vs ignore

What is the difference between insert= and ignore=?
Insert adds the hostname to DB_ACCESS (during a reset=init:0 query), and ignore does not. Because ignore does not add hostnames to DB_ACCESS, the hostnames will only be valid for that query. However, because insert adds the hostnames to DB_ACCESS, subsequent queries will consider the hostnames to have already accessed the counter.

2.1.3  Arst Changes Colors

The Arst image seems to change colors sometimes. Why?
If the link information in DB_COUNTER (default values) has been deleted, and the link's access list is reset, the image will be displayed with compile time default values (usually black and white.)

2.1.4  Broken Image

A broken image is always returned!

2.2  URL Formation

The following contains information necessary to properly create the GET request URL for mod_countm. Although some information is technical in nature, most is not required for simple, everyday use, URL formation.
RFC 1630 establishes a universal method to define a resource, called a Universal Resource Identifier (URI):
scheme:path
The scheme identifies a defined interpretation. Once scheme is defined, the URI becomes a URL.
The exact path format depends on the definition of the scheme, but is generally defined as:
/location/of/resource#fragment?querystring

Within path, /location/of/resource identifies a query-able object. The '/' separating substrings establishes a hierarchical definition of the query-able object. The '#' delimits a fragment within the query-able object. The '?' delimits the query on that object. Within the URI, '%' is used as an escape character for an encoding process. In addition to reserving the '/', '#', and '?' characters, the asterik '*' and the exclamation mark '!' are reserved. Within querystring, '+' is reserved as shorthand for a ' '. Any character that may not be used directly should be encoded. This includes control characters and characters with an ascii value > 127.
RFC 1738 defines the URL within the URI syntax:
<scheme>:<scheme-specific-string>

and expands its definition. Only alphanumerics, "$-_.+!*'()," and reserved characters used for their defined purposes may be used uncoded in a URL. Although the URI reserves the exclamation mark '!' and the asterisk '*', the URL permits them. Currently, mod_countm does not attach any special significance to the '!' and '*' characters (as a shell would for file globing), and should never be required. A future exercise in futility would be to modify mod_countm to interpret the '*' character in a URL as a "match all that is given." Any database link that matched the given URL would be acted upon, presumably incremented, deleted, reset, etc., depending on the command. Requiring spaces to be encoded is common to both standards, but RFC 1630 uses a +, and RFC 1738 uses a triplet. Fortunately, all recent mainstream User Agents translate a space (' ') automatically. Characters other than those allowed or defined must be encoded using % octets.
For http scheme, and family, the URL syntax is:
http://<host>:<port>/<path>?<searchpart>

Within path and searchpart, '/', ';', '%', and '?' are reserved, and have special meaning. The '/' character, within path designates a hierarchical structure, which, mod_countm mainly uses as a separator of logical directories defining a hierarchical set of configuration options, with the lowest, or rightmost, settings having priority, and the highest, or leftmost, replacing missing options. The directories may also define logical query-able objects, such as a dynamic list of all fonts available to the server, or a counter.
The basic format format of a mod_countm URLs is:
<IMG SRC=scheme://host:port/path/PATH_INFO?QUERY_STRING>

2.2.1  QUERY_STRING

The QUERY_STRING represents all characters after the reserved '?' character and is encoded in the RFC 1866 section 8.2.1 form-urlencoded Media Type. The basic format of the QUERY_STRING is:
parameter1&parameter2&..&parameterN

where each parameterN is delineated by the reserved character '&' and formated as a key/ value pair. The key/ value pair is separated by the reserved character '=', and the key is noted as a command, and the value is noted as the parameter_value.
command=parameter\_value

2.3  QUERY_STRING application/x-www-form-urlencoded

Information presented here based on section 8.2 RFC 1866.
The enctype application/x-www-form-urlencoded states: A User Agent (browser) tends to apply application/x-www-form-urlencoded encoding as follows: Mod_countm decodes the QUERY_STRING as follows: When creating the link commands parameter_value, follow these guidelines: Example: Actual parameter_value, as to be entered into the database.
link=http://www.mydomain.com/b+ +stuff/index.html

Would be entered into <FORM> exactly as above.
However, It would be entered into <IMG> as:
link=http://www.mydomain.com/b%2B %2Bstuff/index.html

Just as a note,
link=http://www.mydomain.com/b+ +stuff/index.html

would be encoded by <FORM> as
link=http%3A%2F%2Fwww.mydomain.com%2Fb%2B+%2Bstuff%2Findex.html

and
link=http://www.mydomain.com/b%2B %2Bstuff/index.html

would most likely be encoded by <IMG> as
link=http://www.mydomain.com/b%2B%20%2Bstuff/index.html

In either case, decoding the encoded parameter_value will result in
link=http://www.mydomain.com/b+ +stuff/index.html

2.4  Enter Link in Database.

After installation, no databases exist. BDB databases are created when the first link is entered into a database using the reset=init:0 parameter. MySQL database and tables must be created via the countm utility. To insert a link into the database and set the counter to the initial value:
<IMG src="localhost/countm?link=linkname&reset=init:0">

The image will indicate success with "Cadd". If the link is already present in DB_COUNTER, Ëlink" is displayed. In the above example, no other parameters were entered into the database, so future queries would have to state them on the query command line, or the compile time defaults will be used. Also, the directive CountmAllowReset must be ON.

2.5  Add Image to Document

Add the link count image to the HTML document to be monitored using the <IMG> tag.
<IMG src="localhost/counter?link=linkname">

The image will display the count.
If the link is not present in DB_COUNTER, "NoLink" is displayed.
The browser loading the page containing the <IMG> tag will attempt to retrieve the <IMG> resource. Mod_countm will handle the request and return a generated or modified image containing the current page count.

2.6  Reset Link Count

Add the link count image to a test or temporary HTML document using the <IMG> tag.
<IMG src="localhost/countm?link=linkname&reset=44">

If the link is currently present in the database, the old value is displayed, and count is set to new value.
If the link is not in the database, "NoLink" is displayed.
CountmAllowReset must be ON.

2.7  Reset Access List

Add the link count image to a test or temporary HTML document using the <IMG> tag.
<IMG src="localhost/countm?link=linkname&reset=access">

The image will display Arst (Access Reset).
If the link is not present in the access list, "NoLink" is displayed.
CountmAllowReset must be ON.
The database contains an access list for each link. Each host visiting the monitored link will be entered into the access link. The reset=access command deletes the access list, but does not alter the counter values.

2.8  Delete Link

Add the link count image to a test or temporary HTML document using the <IMG> tag.
<IMG src="localhost/countm?link=linkname&reset=delete">

The image will display Cdel. (Deleted)
If the link is not in the counter database, "NoLink" is displayed.
CountmAllowReset must be ON.
The database maintains a counter value, along with default values, for each link. To delete all default values and any count value, use the reset=delete command.

2.9  A First Entry

<img
src="http://www.localzone/countm/admin?
     link=http://www.mydomain.com/b%2B %2Bstuff/index.html
     &reset=init:34
     &image=png
     &text=FFFFFF
     &bgcolor=9933FF
     &count=norm_inc
     &point=20
     &random=false
     &width=0
     &font=FreeMono.txt
     &insert=localhost
     &insert=localhost.localdomain
     &insert=www.hackedme.jerk"
>

For the above example, the link
http://www.mydomain.com/b+ +stuff/index.html

is inserted into the database. Note: the IMG tag SRC elements + signs are encoded. If using BDB and the database does not exist, it will be created. If using MySQL, the database and tables must exist prior to mod_countm usage. The counter value will start at 34, the returned image will be png, the text of the returned image will be FFFFFF (white), the background color of the returned image will be 9933FF (a purple), the text font will be FreeMono, and the text size will be 20 point. The counter mode will be norm_inc, which means only unique hostnames will increment the counter value in DB_COUNTER. The random mode will be false, which means that the returned image will display the actual count in DB_COUNTER. If random mode was true, then a random value would be returned. The width will be set to 0, which means any returned value will use exactly the necessary number of digits to display the number. The three insert commands add the hostnames localhost, localhost.localdomain, and www.hackedme.jerk to DB_ACCESS.
After inserting the above example, dump the database to verify proper operation
#countm -dbenv=/var/countm/dbase -dbfile=countm.db L
LINK:http://www.mydomain.com/b+ +stuff/index.html
DB_COUNTER:
countval=34
image=png
count=norm_inc
random=false
atime=May 05 2004
width=0
point=20
bgcolor=9933FF
text=FFFFFF
font=FreeMono.ttf
DB_ACCESS:
localhost
localhost.localdomain
www.hackedme.jerk

Or, use db_dump:
#db_dump -p /var/countm/dbase/countm.db
VERSION=3
format=print
database=DB_ACCESS
type=hash
h_nelem=1
duplicates=1
dupsort=1
db_pagesize=4096
HEADER=END
 http://www.mydomain.com/b+ +stuff/index.html\00
 localhost\00
 http://www.mydomain.com/b+ +stuff/index.html\00
 localhost.localdomain\00
 http://www.mydomain.com/b+ +stuff/index.html\00
 www.hackedme.jerk\00
DATA=END
VERSION=3
format=print
database=DB_COUNTER
type=hash
h_nelem=1
db_pagesize=4096
HEADER=END
 http://www.mydomain.com/b+ +stuff/index.html\00
 "\00\00\00\01\00\00\00\03\00\00\00\01\00\00\00\1f\00\00\00\00\00\00\00\14\00
 \00\00\99\00\00\003\00\00\00\ff\00\00\00\ff\00\00\00\ff\00\00\00\ff\00\00\00
 May 05 2004\00FreeMono\00
DATA=END

2.10  A Complete Session

The following assumes a new installation, defining a global server only. The above sequence enters a link into the database, then queries the link and returns the counter value. For this sequence, ex_query.html would be considered the document being monitored. After querying the counter, the value is reset, then the access list is reset, and, finally, the count is deleted from the databases.

2.11  Fonts/ Query Available Fonts

Any directory containing fonts to be used by mod_countm must be accessible by runtime Apache. Also, the fonts within the directory must be readable by runtime Apache.
Mod_countm uses libgd to create and/or manipulate the returned image. libgd DBFONTPATH environmental variable or the gd.h compile time option DEFAULT_FONTPATH is used by libgd to locate TrueType fonts if the font name does not contain any directory separator characters. Also, libgd will automatically check valid TrueType font name extensions, so font names may not have extensions. However, if the font name contains a directory separator character, then libgd uses the font name directly, bypassing the font path scheme. To force libgd to use the font name directly, define the mod_countm CountmFontDir directive. Mod_countm will appended the font name to CountmFontDir, and will be used directly by libgd, bypassing the automatic font location scheme. When CountmFontDir is defined, all font names must include the extension.
Decide on a font location strategy. Sites comfortable allowing server access to system font directories and/or setting environment variables should use DBFONTPATH, avoid defining CountmFontDir, and specify all font names as base font names, without any directory separators or extensions. Sites wanting to restrict all server font access to a specific directory hierarchy should define CountmFontDir, and use font name extensions.
When changing the font location strategy, the databases, and all information within them, must be deleted. Otherwise, any font name within the database will be incorrect.
The list fonts query will return the list of "known" fonts based on CountmFontDir. If CountmFontDir is not defined, the fonts listed are font names that match the extensions from GDFONTPATH or DEFAULT_FONTPATH (without extensions). Otherwise, they are the names of files, (with extensions) from within CountmFontDir listed recursively.
Avoid the critical error: Always adjust CountmDefFont extension after defining/ removing CountmFontDir directive.
The COUNTM_EXTENSIONS_TTF compile time option defines a PCRE that mod_countm thinks is what libgd uses for TrueType font filename extension. It is set for gd-2.0.21.
Setting the per directory config directive AllowFontsQuery option to ON activates the font query capability.
A mod_countm request with PATH_INFO /fonts will return a listing of all known TrueType fonts. Symbolic links are not followed. No check is made to see if the file actually is a valid font. If CountmFontDir is defined, all files within CountmFontDir are assumed to be valid TrueType fonts. If countmFontDir is not defined, all files with COUNTM_EXTENSIONS_TTF extensions within GDFONTPATH or DEFAULT_FONTDIR are assumed to be valid TrueType fonts.
The returned listing is printed exactly as each font should be entered into the font= command.
Correct operation is also dependent on non mod_countm per server and per directory access configuration directives.
Example:
http://localhost/countm/fonts

The gd.h DEFAULT_FONTPATH may not be correct for all installations of gd. In most cases, it is probably correct. Irregardless, if GDFONTPATH is not defined, it is used.
<

2.12  QUERY_STRING parameters

2.12.1  font

font=font_name
Default: font=FreeMono
The TrueType font for the counter image text/digits. A font error is indicated by Ëfont".

2.12.2  width

width=counting_number
Default width=0
The number of digits displayed. If the returned count requires more digits, then Ëovr" is returned. If the background image may not display all the digits, then Eovr is returned. A width=0 will use exactly the number of digits required (default). Normally only used with random command. Returned error/information strings always use width=0. The max value is 9 (MAX_WIDTH_CHAR_DISPLAY). If the width is greater than the number of digits, then leading zeros are added to fill width.

2.12.3  random

random=[true,false]
Default random=false
If true, then instead of displaying the count value, display a random value. The access list and counter information is adjusted according to current settings.

2.12.4  reset=access

reset=access
The links' access list is removed from the database. Success is indicated by the returned image Ärst". If link is not currently in the database, "NoLink" is returned.
If the CountmAllowReset httpd configuration directive does not allow reset= query command line options, Ëparm" will be returned for all queries that have a reset= parameter on the query command line.

2.12.5  reset=delete

reset=delete
The links' counter value is removed from the database. Success is indicated by the returned image "Cdel". If the link has an access list, it remains in the database. If the link is not currently in the database, "NoLink" is returned.
If the CountmAllowReset httpd configuration directive does not allow reset= query command line options, Ëparm" will be returned for all queries that have a reset= parameter on the query command line.

2.12.6  reset=counting_number

reset=counting_number
If the link exists in DB_COUNT, then the counter value is changed to counting_number, and the current counter value is returned. If the link does not exist in the database, "NoLink" is returned.
If the CountmAllowReset httpd configuration directive does not allow reset= query command line options, Ëparm" will be returned for all queries that have a reset= parameter on the query command line.

2.12.7  reset=init:counting_number

reset=init:counting_number
Insert the link into the counter database (DB_COUNTER), set the the values on the command line as defaults, initialize the counter start value to counting_number, and return "Cadd". Any parameters given during the counter reset/ initialization phase will become the link defaults, and not be required on subsequent calls. On subsequent queries, compile time option COUNTM_INFORMATION_PRIORITY specifies if the command line values take priority, or if the database options take priority. Default is COUNTM_INFORMATION_PRIORITY_DATABASE. If the link is already present in the counter database (DB_COUNTER), Ëlink" is returned, and the current database values for the link are not changed.
If the CountmAllowReset httpd configuration directive does not allow reset= query command line options, Ëparm" will be returned for all queries that have a reset= parameter on the query command line.

2.12.8  image

image=[jpeg, png]
The return image format. If the module has been compiled with USE_PNG_IF_ACCEPTABLE, and the requesting client accepts png images, then a png image will be returned.

2.12.9  point

point=number
The point size of the font.

2.12.10  link

link=linkname
The linkname to be associated with this counter.

2.12.11  ignore

ignore=[IPADDR, DOMAINNAME]
For this query only, these cannot adjust the counter.
The ignore=value value may be of the form IPADDR@mask_or_numbits (192.168.1.0@24 or 192.168.1.0@255.255.255.0) to indicate that a request with ip address in the subnet is not allowed to adjust the counter. The @ notation instead of the usual / is a implementation issue.

2.12.12  text

text=000000
The font color using "web color" rgb triplet notation (HEX, do not use a leading 0x).

2.12.13  bgcolor

bgcolor[000000, filename_jpeg, filename_png]
bgcolor=000000
The image background color, specified with "web color" rgb triplet notation (HEX, do not use a leading 0x).

bgcolor=filename_jpeg
bgcolor=filename_png
A image to use as the returned images background. The size of the background image determines exactly the size of the returned image. The count string is centered within the image. If the count string will not fit within the image, a error is returned. If the image may not be accessed, or is not a valid jpeg or png image, the default background is used. If the bgcolor value matches the COUNTM_EXTENSIONS_JPEG or COUNTM_EXTENSIONS_PNG extension, it is assumed to be a valid background image file within CountmBgfileDir. Otherwise, it is assumed to be a RGB hex value.

2.12.14  count

count=[inc, inc_nopub, dec, dec_nopub, norm_inc, norm_dec]

count=inc
Specifies that the count should be incremented without checking DB_ACCESS. If host is not in DB_ACCESS, host is entered into DB_ACCESS.

count=inc_nopub
Specifies that the count should be incremented without checking DB_ACCESS. If host is not in DB_ACCESS, host is entered into DB_ACCESS. If the request remote ip address is from an RFC 1918 public network, do not adjust the counter.

count=dec
Specifies that the count should be decremented without checking DB_ACCESS. If host is not in DB_ACCESS, host is entered into DB_ACCESS.

count=dec_nopub
Specifies that the count should be decremented without checking DB_ACCESS. If host is not in DB_ACCESS, host is entered into DB_ACCESS. If the request remote ip address is from an RFC 1918 public network, do not adjust the counter.

count=norm_inc
Specifies that the count should be incremented if host is not in DB_ACCESS. If host is not in DB_ACCESS, host is entered into DB_ACCESS.

count=norm_dec
Specifies that the count should be decremented if host is not in DB_ACCESS. If host is not in DB_ACCESS, host is entered into DB_ACCESS.

2.12.15  insert

insert=hostname
This hostname is added to DB_ACCESS. Only valid during reset=counting_number query if and only if the link is not in DB_COUNT. Multiple insert commands may be used.

Chapter 3
Module Configuration

Configuring mod_countm for use within the Apache2 server environment requires setting mod_countm configuration directives and, optionally, Apache2 configuration directives.
The mod_countm.conf file contains the default apache2 mod_countm configuration directives.
Ordering of the <Location> directives are important. The first <Location> directive must be (at least):
<Location /countm>
	SetHandler mod-countm
</Location>

Apache 2 Location directive documentation states that Location sections are processed in order of appearance in the configuration files. If this section is not first, the first parameter to the module per dir merge function will be incorrect. The best solution would probably be to add it to the main config file (httpd.conf) prior to any Include *.conf statements, or other countm location sections. Additional <Location /countm/whatever> sections must follow the <Location /countm> section.
Mod_countm does not support nested virtualhost sections, but neither does Apache2.
For best results, always activate the global CountmActivate directive and alway define a global database. Virtual servers then have the option of using the global database, using a unique database, or setting CountmActivate to OFF, and not serving any countm queries.

3.1  CountmFontDir

Description:   ¯Directory containing true type fonts.
Syntax:  CountmFontDir /Absolute/path/to/dir/string
Context:  Server Config
Status:  Extension
Module:  mod_countm.so
See Also:  CountmDefFont CountmFontDir is an absolute path (no ending directory separator '/') of a directory containing TrueType fonts. The directory must be readable. The directory must have the correct ownership and permissions for runtime server access. See the Apache configuration User and Group directives. If defined, the complete path must exist at startup. A missing CountmFontDir directive is considered not defined.
Any file within CountmFontDir will be considered a valid true type font. If it is not, a runtime error will result when mod_countm attempts to use it.
If CountmFontDir is defined, all font names are considered relative to CountmFontDir and must include the necessary extensions. GDFONTPATH and DEFAULT_FONTPATH are ignored.
If CountmFontDir is not defined, then standard GD font location procedures using GDFONTPATH and DEFAULT_FONTPATH apply. Relative and absolute font names are invalid. Font base names are required, which implies no extension.
If the global server defines CountmDefFont: A virtual server without a CountmDefFont will inherit the global server value. Virtual servers must use base font names. If the global server does not define CountmDefFont: Virtual servers that do not define CountmDefFont must use base font names. Virtual servers that define CountmDefFont must use relative font names with extensions, or font names with extensions. Font names stored in DB_COUNTER create runtime problems if the CountmFontDir setting is altered from defined to not defined. When changing mod_countm configuration from (or to) a defined CountmFontDir to (or from) a non defined CountmFontDir, always delete and reset the database. Changing the CountmFontDir value (as opposed to defined/not defined) does not alter any DB_COUNTER font names.

3.2  CountmDefFont

Description:   ¯The default true type font.
Syntax:  CountmDefFont fontname
Context:  Server Config
Status:  Extension
Module:  mod_countm.so
See Also:  CountmFontDir CountmDefFont is the name of the default mod_countm TrueType font. The default font is used to return error values, replace missing font= parameter_values, or replace incorrect font= parameter_values. The fonts must be readable and have correct ownership for runtime server access. A missing CountmDefFont is considered not defined and is an error.
When defining CountFontDir, alway use an extension with CountmDefFont. See CountmFontDir for more information.

3.3  CountmEnvironmentHome

Description:    ¯Berkeley DB4 database environment home directory.
Syntax:  CountmEnvironmentHome /Absolute/path/to/dir/string/
Context:  Server Config
Status:  Extension
Module:  mod_countm.so
See Also:  CountmDB CountmEnvironmentHome is the absolute pathname (with a trailing directory separator) of the counter database environment/home. All per server database files are relative to this directory. The directory must be writable, and have correct ownership for runtime server access. If defined, the entire directory path must exist at startup. A missing CountmEnvironmentHome directive is considered not defined.

3.4  CountmDB

Description:   ¯Berkeley DB4 database filename.
Syntax:  CountmDB valid_file_name_string
Context:  Server Config
Status:  Extension
Module:  mod_countm.so
See Also:  CountmEnvironmentHome CountmDB is the name of the database file, (no directory separators allowed), and is relative to CountmEnvironmentHome. A DB_COUNTER and a DB_ACCESS sub database are created within this file. A missing CountmDB directive is considered not defined.

3.5  CountmMySQL

Description:    ¯MySQL Database configuration information.
Syntax:  CountmMySQL öption1" öption2" ... öptionN"
Context:  Server Config
Status:  Extension
Module:  mod_countm.so
CountmMySQL sets the per server MySQL database configuration. Required for MySQL database support. Each optionN value sets a configuration value. Very little checking, if any, is performed on the values. If they are not correct, then runtime errors will result in a deactivated server counter. Each optionN is in the form -parameter=value. The leading parameter dash '-' is required. All characters following the equals '=' and up to but not including the separating spaces ' ', are considered the value.
-host=The host name or IP address.
-user=The user ID. (Required.)
-passwd=The password for user.
-db=The database. (Required)
-port=The port.
-unix_socket=The socket or Named pipe.
-opt_group=The MYSQL_READ_DEFAULT_GROUP value.
-opt_file=The MYSQL_READ_DEFAULT_FILE value.
Must have runtime permissions to access opt_file.

Ex: (unix)
CountmMySQL -host=waiter -user=joe -passwd=yippee -opt_group=joe_counter -opt_file=/home/joe/joe.mysql

The -passwd=value value is stored by mod_countm in plaintext. The MySQL client API automatically encrypts it prior to usage.
All of the above values are subject to per server merging. Global server values will become default values for any virtual servers undefined values. This is an especially important consideration for the -passwd value.
An optionN parameter using a ' ' (space) character should be enclosed within quotes ("). An optionN parameter using a quote (") should use a backslash quote.

3.6  CountmDBLockFile

Description:   ¯Global DB4 lockfile.
Syntax:  CountmDBLockFile /Absolute/path/and/file_name_string
Context:  Server Config
Status:  Extension
Module:  mod_countm.so
CountmDBLockFile is the absolute path and filename of a file to be used, by mod_countm, as a possible locking mechanism. If AcceptMutex is set to LockFile, the CountmDBLockFile will be used at runtime. The directory containing the lockfile must be writable and have correct ownership to allow for runtime server access. This directive must be defined for the global server and is ignored if defined for virtual servers. A missing CountmDBLockFile is considered not defined, and is an error.

3.7  CountmBgfileDir

Description:   ¯Background images directory.
Syntax:  CountmBgfileDir /Absolute/path/name/string
Context:  Server Config
Status:  Extension
Module:  mod_countm.so A runtime readable directory string (no trailing /) containing png or jpeg background images. If defined, the complete directory path must exist at startup. A missing CountmBgfileDir is considered not defined. All files within the directory, if any, are assumed to be jpeg or png images. Any file with a .jpeg (exactly) extension is assumed to be a valid jpeg image. Any file with a .png (exactly) extension is assumed to ba a valid png image.

3.8  CountmActivate

Description:   ¯Controls the servers response to requests.
Syntax:  CountmActivate [ON, OFF]
Context:  Server Config
Status:  Extension
Module:  mod_countm.so CountmActivate ON
Activates the counter for the server.

CountmActivate OFF
Ignores all countm requests to this server. Also, does not internally process the server directives, or open/access the database that may be defined.
A missing CountmActivate directive is considered not defined.
When ignoring requests, returns a HTTP_NOT_FOUND message, which usually means a broken image.

3.9  CountmAllowReset

Description:   ¯Controls servers reset= command handling.
Syntax:  CountmAllowReset [ON,OFF]
Context:  directory/location
Status:  Extension
Module:  mod_countm.so CountmAllowReset ON
Activates the reset= query command.
CountmAllowReset OFF
Deactivates the reset= query command. Any queries using the reset= query command will return Eparm. Because no link is associated with the returned image, the compiled in defaults and default font will be used.
A missing CountmAllowReset directive is considered not defined.

3.10  CountmDBPriority

Description:   ¯Determines the priority of the database.
Syntax:  CountmDBPriority [ON,OFF]
Context:  directory/location
Status:  Extension
Module:  mod_countm.so CountmDBPriority ON
All defined parameters (have a valid value) in the database are used to construct the returned image, even if new parameters (have a valid value) are given on the query command line. These values are entered using the reset=init:# command, or, after the database is created, the countm utility.
CountmDBPriority OFF
Any defined parameters (have a valid value) on the query command line will be used to construct the returned image, even if the same parameters are already defined (have a valid value) in the database.
A missing CountmDBPriority directive is considered not defined.

3.11  Undefined Directives

Undefined virtual server directives inherit the global server directives values. Undefined per directory directives inherit the values of the per directory settings above it.

3.12  CountmDB, CountmEnvironmentHome, and CountmActivate

3.12.1  Assigning A Database

The database assigned to a server depends on the CountmEnvironmentHome and CountmDB directives. Defined directives will be used directly. Undefined directives may inherit values from the global server. At runtime, an undefined database directive is only allowed for an inactive (CountmActivate OFF) server, or a server using the global database. Otherwise, CountmActivate is forced OFF. These rules may be used to assign a group of servers to a specific database, allow some, none, or all virtual servers to default to the global database, or define a unique database for each server.

3.12.2  Activating Databases

Mod_countm officially requires the global server to define a database and set CountmActivate ON. For this configuration, each virtual server choosing to to redefine the database parameters will use the globals servers database. However, attempts have been made to accommodate a variety of situations where this is not true.
Defining the global CountmActivate to OFF implies that the global server does not define a database, and all virtual servers CountmActivate will be OFF. Virtual servers that set CountmActivate ON must define a database. Here, although the global server is OFF, if the database directives are defined, they can be inherited to effect a global database.

3.13  Commandline VS Database Priority

Information (parameters) given in QUERY_STRING during a reset=init command are inserted into the database and may be used to replace missing parameters/values on subsequent requests. Those subsequent requests may specify different values for certain parameters. If the priority is database, the defined parameters' parameter_values in the database will always be used, even if new parameter values are specified on subsequent queries command lines. If the priority is commandline, then the parameter values on subsequent queries command line will be used, even if a value for the parameter is already in the database.
The usage of priority database decreases security holes. Assuming all administration reset= commands are restricted to localhost, and all parameters are defined and entered into the database during reset=init, all future QUERY_STRING parameters except link= are ignored, and the values in the database are used.

3.14  Apache2 HostNameLookups Directive

HostNameLookups [ON,OFF,DOUBLE]
If HostNameLookups is OFF inside the location directive, the Apache 2 api will return the remote IP address as the hostname, and mod_countm will use the remote client IP address as a hostname.
If HostNameLookups is ON inside the location directive, the Apache 2 api will use single lookup to get the hostname. If there is a hostname, mod_countm will use the remote client hostname, otherwise, mod_countm will use the IP address as the hostname. This reduces performance, as a remote hostname single lookup is required for each query. If HostNameLookups is DOUBLE inside the location directive, the Apache 2 api will use double reverse lookup to get the hostname. Double reverse lookup in this context means that a list of IP addresses is obtained for the hostname returned from single reverse lookup. If the stated IP address matches one in the returned list, then the hostname is returned. Otherwise, an error is returned. When double reverse lookup succeeds, mod_countm uses the returned hostname as the hostname. Otherwise, mod_countm will log the failure, and return Ëconn". If HostNameLookups are OFF and the remote host is still being identified as a hostname, and not an IP address, the compile time parameter COUNTM_FORCE_HOSTNAMELOOKUPS must be set to 1, and the module recompiled. Setting compile time option COUNTM_FORCE_HOSTNAMELOOKUPS to 1, and using HostNameLookups [ON, DOUBLE] is acceptable, but performance is reduced due to required additional reverse or double reverse lookups. If HostNameLookups is DOUBLE, and you would like to force a failed double reverse lookup to return an error, then COUNTM_FORCE_HOSTNAMELOOKUPS must be set to 1.

Chapter 4
Configuration Examples

4.1  Configuration Zero

4.2  Configuration One

The simplest setup is to use on global database for all servers. Each server, when answering mod_countm queries would use the same database.
<Location /countm>
    SetHandler               mod-countm
    HostNameLookups          ON
    CountmAllowFontsQuery    ON
    CountmAllowReset         ON
    CountmDBPriority         ON
</Location>
LoadModule countm_module @libexecdir@/mod_countm.so
CountmFontDir                "/var/countm/fonts"
CountmDefFont                "FreeMono"
CountmEnvironmentHome        "/var/countm/dbase"
CountmDB                     "countm.db"
CountmDBLockFile             "/var/countm/countm.lock"
CountmBgfileDir              "/var/countm/bgfiles"
CountmActivate               ON

This basic configuration defines one database, which all servers will use, and defines one logical queryable object which will allow a font listing query, use of the reset= command, and use database priority. All information in the database will refer to the accessing host as a hostname, if one exists. All servers will use the same default font, and share the fonts in the fonts directories.
An HTML 4.0 <FORM> Element Attribute ACTION URL PATH_INFO to enter the counter into the database would be /countm.
Example: <form action=http://my.domain.com/countm method=GET enctype="x-www-form-urlencoded» Somewhere in the form, an HTML 4.0 INPUT Element with an attribute NAME link attribute VALUE linkname would set the ?link=linkname portion. In some rare cases, a / trailing countm may be necessary.
Once the counter is entered into the database, it may be accessed by the page being counted using a HTML 4.0 IMG element "Query URL". For this example,
<img src="http://my.domain.com/countm?link=linkname» Generally, only one countm IMG element per page works.
If the link linkname is not in the database (has not been entered), then an image ËLink" should be returned, not a broken image.
An IMG element attribute SRC value using the localhost (or 127.0.0.1) as the domain name will always return a broken image when the accessing client is not on the local machine.
Using the IPV4 address of the server in place of any hostnames (ie 127.0.0.1 instead of localhost) would rule out any problematic resolver issues.

4.3  Configuration Two

Defining additional logical query-able objects increases access control and defining additional databases adds per server statistics.
<Location /countm>
    SetHandler               mod-countm
    HostNameLookups          ON
    CountmAllowFontsQuery    OFF
    CountmAllowReset         OFF
    CountmDBPriority         ON
</Location>

<Location /countm/admin>
    CountmAllowReset        ON
    Order                   deny,allow
    Deny                    from all
    Allow                   from 127.0.0.1
    Allow                   from localhost
    Allow                   from 192.168.1
</Location>

<Location /countm/fonts>
   CountmAllowFontsQuery   ON
</Location>

LoadModule countm_module @libexecdir@/mod_countm.so
CountmFontDir                "/var/countm/fonts"
CountmDefFont                "FreeMono"
CountmEnvironmentHome        "/var/countm/dbase"
CountmDB                     "countm.db"
CountmDBLockFile             "/var/countm/countm.lock"
CountmBgfileDir              "/var/countm/bgfiles"
CountmActivate               ON

<VirtualHost www.localzone:80>
    ServerName               www.localzone:80
    CountmDB                 "countm_virt.db"
</VirtualHost>

This example adds an admin and fonts object. A request to just /countm will be restricted to non reset= commands, but all requests are accepted. A request to /countm/admin will allow reset= command, but only from localhost, 127.0.0.1, and public network 192.168.1, presumably behind a firewall. Also, www.localzone will use a separate database file countm_virt.db, but share a database environment with the global server. Locks will be shared across both global and virtual servers database files. Both servers will use the same default font, and share the fonts in the fonts directories.

4.4  Configuration Three

Defining additional logical query-able objects increases access control and defining additional databases adds per server statistics.
<Location /countm>
    SetHandler               mod-countm
    HostNameLookups          ON
    CountmAllowFontsQuery    OFF
    CountmAllowReset         OFF
    CountmDBPriority         ON
</Location>

<Location /countm/admin>
    CountmAllowReset        ON
    Order                   deny,allow
    Deny                    from all
    Allow                   from 127.0.0.1
    Allow                   from localhost
    Allow                   from 192.168.1
</Location>

<Location /countm/fonts>
   CountmAllowFontsQuery   ON
</Location>

LoadModule countm_module @libexecdir@/mod_countm.so
CountmFontDir                "/var/countm/fonts"
CountmDefFont                "FreeMono"
CountmEnvironmentHome        "/var/countm/dbase"
CountmDB                     "countm.db"
CountmDBLockFile             "/var/countm/countm.lock"
CountmBgfileDir              "/var/countm/bgfiles"
CountmActivate               ON

<VirtualHost www.localzone:80>
    ServerName               www.localzone:80
    CountmEnvironmentHome    "/var/countm/virt_dbase"
    CountmDB                 "countm_virt.db"
</VirtualHost>

This example is the same as example two, but uses a separate environment for each database file. Locks will not be shared.

4.5  Configuration Four

Here is a crazy, powerful, and realistic example:
# Example 4
<Location /countm>
    SetHandler               mod-countm
    HostNameLookups          ON
    CountmAllowFontsQuery    OFF
    CountmAllowReset         OFF
    CountmDBPriority         ON
</Location>

<Location /countm/admin>
    CountmAllowReset        ON
    Order                   deny,allow
    Deny                    from all
    Allow                   from 127.0.0.1
    Allow                   from localhost
    Allow                   from 192.168.1
</Location>

<Location /countm/fonts>
   CountmAllowFontsQuery   ON
</Location>

LoadModule countm_module modules/mod_countm.so

# Global sever configuration
# The Global Server counter is not active
# The Global Server CountmEnvironmentHome directive is not defined.
CountmFontDir                "/var/countm/fonts"
CountmDefFont                "FreeMono"
CountmDB                     "countm.db"
CountmDBLockFile             "/var/countm/countm.lock"
CountmBgfileDir              "/var/countm/bgfiles"
CountmActivate               OFF

# 192.168.1.241
# Results in an active counter /var/countm/dbase1/countm.db
<VirtualHost www1.localzone:80>
    ServerName               www1.localzone:80
    CountmEnvironmentHome    "/var/countm/dbase1"
    CountmActivate           ON
</VirtualHost>

# 192.168.1.242
# Results in an active counter /var/countm/dbase2/countm.db
<VirtualHost www2.localzone:80>
    ServerName               www2.localzone:80
    CountmEnvironmentHome    "/var/countm/dbase2"
    CountmActivate           ON
</VirtualHost>

# 192.168.1.243
# Results in an active counter /var/countm/dbase3/countm.db
<VirtualHost www3.localzone:80>
    ServerName               www3.localzone:80
    CountmEnvironmentHome    "/var/countm/dbase3"
    CountmActivate           ON
</VirtualHost>

# 192.168.1.244
# Results in an inactive counter
# Add CountmActivate ON to activate
<VirtualHost www4.localzone:80>
    ServerName               www4.localzone:80
    CountmEnvironmentHome    "/var/countm/dbase4"
</VirtualHost>

# 192.168.1.245
# Results in an inactive counter and a warning message.
# CountmEnvironmentHome is not defined.
<VirtualHost www5.localzone:80>
    ServerName               www5.localzone:80
    CountmActivate           ON
</VirtualHost>

# 192.168.1.246
# Results in an active counter, shared with www3
<VirtualHost www6.localzone:80>
    ServerName               www6.localzone:80
    CountmEnvironmentHome    "/var/countm/dbase3"
    CountmActivate           ON
</VirtualHost>

Notice that the global server defines CountmDB, but not CountmEnvironmentHome, and that it is not active (CountmActivate OFF). This means that all virtual servers will be inactive (like www4.localzone) unless specifically set to ON, and all virtual servers that do not redefine CountmDB will inherit the global configuration "countm.db" value. Servers www1, www2, www3, and www6 are active, and define unique environment home directories, so they will not share locks with other database files sharing a common environment, increasing performance. Virtual server www5 does not define CountmEnvironmentHome and cannot inherit a valid value from the global server. Although CountmActivate is ON, virtual server www4 will be forced inactive, and a warning message issued. Virtual servers www3 and www6 will share database dbase3/countm.db. All virtual servers will use the same default font, and access the fonts from the same font directory.
Mod_countm will ignore requests for global server www and virtual server www4 and www5 due to their inactive counters, normally returning a Not Found page. Requests to www1-3, an www6 will be accepted, because they are active.

Chapter 5
libcountm

The mod_countm build process creates and install libcountm. The configure option -enable-versioning will enable building a versioned libcountm if the compiler supports the .symver directive and the linker supports the -version-script option.
Almost all of the following is specific to ELF 32bit, default for FC3/i386.

5.1  symbol versioning

Associated with libcountm are numerous pieces of version and location information.
The most recent interface number exported, IFACE_N.
The interfaces the library exports.
The library versioning information, C:R:A.
The library object version info, .x.y.z.
The link/compile time library name, usually libcountm.so.
The link/compile time library location.
The runtime linker library name, usually libcountm.so.x.
The library object file name, usually libcountm.so.x.y.z.
The runtime location of the library.
The two i386 32bit ELF sections of interest are .dynstr and .dynamic. These are only created if dynamic linking is requested (default.) In the execution view of the ELF object file, the .dynamic segment is available if an element in the program header has p_type PT_DYNAMIC. The .dynamic section is an array of elements, some of which are DT_STRTAB, DT_SONAME, DT_RPATH, and DT_NEEDED. DT_STRTAB points to the .dynstr section, DT_NEEDED (may be duplicates) points to a NEEDED name entry in .dynstr, DT_SONAME points to the SONAME of the file, DT_RPATH (may be duplicates) points to a RPATH name in .dynstr.
During the libcountm build link time, SONAME is set inside the libcountm.so.x.y.z library object. Objdump -p libbky.so.x.y.z will list the internal SONAME setting. Normally, this is libcountm.so.x.
An object linked to libcountm must identify the library at build link time using the -lcountm and -L/path/to/installation options. The build time linker finds libcountm.so in the -L path and uses the libcountm.so SONAME value to set the NEEDED value in the created object (either a binary or a library). If a -rpath was stated, then the RPATH is set also. Use objdump -p name_of_object to view the NEEDED and, if any, RPATH values of the created object. Normally, RPATH is only set if the library is in a location unknown to the application opening the library (either the runtime linker or an application using a dlopen function.)
During libcountm installation, 3 files are typically created, libcountm.so, libcountm.so.x, and libcountm.so.x.y.z. Normally libcountm.so is a symlink pointing to libcountm.so.x and libcountm.so.x is a symlink pointing to libcountm.so.x.y.z. libcountm.so.x.y.z is the actual libcountm library object. libcountm.so is used by the build time (compile/link) linker to locate libcountm. libcountm.so.x is used by the runtime linker to locate the libcountm exporting the correct interface for the application being run.
At load/runtime, the loader (either the runtime dynamic linker or an application opening the library using a dlopen function) uses the objects' (either a binary or a library) NAME value as the name of the library to load. The loader looks for the library in one of the locations it knows about or, if one is in the load object, in the RPATHs. Environmental variables also may be used to determine the runtime location of a library.
When the libcountm library is updated, the new libcountm.so.x.y.z file is installed. However, depending on the exported interface compatibility, the libcountm.so.x value will either be changed, or a new one added. The interfaces exported by the new libcountm determines the manner in which it is installed.
If existing interfaces do not change (the newly installed library is just a revision change of the existing exported interfaces), then the existing libcountm.so.x will be changed to point to the newly installed libcountm.x.y.z+1 library.
If a new interface is added, but does not break any old interfaces, then y will increase, but the existing libcountm.so.x will be changed to point to the newly installed libcountm.so.z.y+1.0 library.
If a new interface was added, which breaks old interfaces, then an new libcountm.so.x+1 will be created, pointing to the new libcountm.so.x+1.y.0. The y value may change to zero, remain the same, or increase depending on the type of interface changes. Also, x may change by two, but usually changes by one. Assuming no interfaces are dropped from the library, the old libcountm.so.x, libcountm.so.x-1 ti libcountm.so.0 values (if any) are altered to point to the newly installed libcountm library.
By versioning all symbols in the libcountm library, and maintaining each interface, the new libcountm library may be used for all objects that have been linked against any version of libcountm without having to recompile the application binaries and/or libraries.
This is all accomplished by strictly following the versioning sequence in the libtool manual, and diligently and judiciously updating the versioning script map file each release.
When a new interface is added, create a new IFACE number. Any interface that is compatible with it is added as a dependency. If a function in a previous interface changes then the ifaceN_fname remains as local to that interface, and the versioned symbol fname@IFACE_N remains. However, a new function ifaceY_fname is created, assigned local to IFACE_Y, and a new versioned symbol fname@IFACE_Y is created. Using objdump -T lib_name will list all the versioned symbols in the library.
Applications will know what version of symbols are required from libcountm at runtime. Each symbol the application requires is versioned, using version_symbolfrom libcountm.h, to the most recently exported interface. The programmer needs only to use the function, in the current interface form, to link with the versioned symbol. As long as the current libcountm library maintains the interface, the binary may runtime link with the new libcountm, and the binary does not require recompiling.

5.2  Interface Numbers

Symbols in libcountm are associated with an interface, identified by IFACE_N. N is the interface number. Interfaces, once defined, must alway export the same functions using the same parameters. If the function parameters in an interface must change, or a function is added to an interface, a new interface must be created. In the case of a function being added, the new interface will be compatible with the old interface. If a function parameter must change, then a new, incompatible interface is created with the new function.

5.3  Interface Functions

The functions in an interface are exported as versioned symbols. The actual function is identified by the local symbol ifaceN_fname. Then, the libcountm.h header file versions fname to fname@IFACE_N. The programmer simply refers to function fname in the normal manner.
Example. Consider function fone with prototype as follows: int fone(int i); The actual function definition for IFACE_0 is: int iface0_fone(int i) return 0; IFACE_0 exports it as fone@IFACE_0. Later, a parameter is added to fone, changing the prototype to: int fone(int i, int k); This breaks interface compatibility and a new interface IFACE_2 is created. The new fone is exported by IFACE_2 as fone@IFACE_2, but the old fone remains as fone@IFACE_0. New executable binaries (at compile/link time) linked with the new version of libcountm will link with fone@IFACE_2, and, at runtime will link with fone@IFACE_2. Old executable binaries will know they require fone@IFACE_0, and, at runtime link time will link with fone@IFACE_0.

5.4  Libcountm Versioning Infomation

The library versioning information, C:R:A is passed to libtool via the -version-info option. As described in the libtool manual, C is the current, most recent interface exported by the library. R is the revision number indicating the number of changes in the implementation of the interfaces since a new interface was added. A, Age, is the number of previous additional compatible interfaces supported and exported by the library.

5.5  Libcountm Object File Information

The library object file uses an extension of the form .x.y.z. x+y+1 is the number of interfaces the library exports. x+y is the interface number of the most recent, current interface. Interface numbers start at 0. z is R. x is the interface number of the first compatible interface. y is the number of compatible interfaces above x.

5.5.1  Example .0.1.1

x=0 y=1 z=1 This library exports 2 interfaces, IFACE_0, IFACE_1. IFACE_1 is the most recent, current interface. IFACE_0 is the first compatible interface. There is one interface compatible with IFACE_0, IFACE_1. This is the first revision since adding IFACE_1.

5.5.2  Example .2.0.0

x=2 y=0 z=0 This library exports 3 interfaces, IFACE_0, IFACE_1, IFACE_2. IFACE_2 is the most recent, current interface. IFACE_2 is the first compatible interface. There are no interfaces compatible with IFACE_2. There have been no revisions since adding IFACE_2.

5.6  Runtime Library Name

The runtime library name (SONAME), usually libcountm.so.x, must change to point to the new library. Consider the installation for libcountm.so.0.1.1.
libcountm.so -> libcountm.so.0 libcountm.so.0 -> libcountm.so.0.1.1 libcountm.so.0.1.1
When the libcountm.so.2.0.0 library is added, the new interface IFACE_2 breaks compatibility with all previous interfaces, but, because of versioning, it may still be used by binaries without recompiling. However, the SONAME of libcountm.so.2.0.0 is libcountm.so.2, to indicate that a previous interface has been broken. When installed, it looks like this: libcountm.so -> libcountm.so.2 libcountm.so.2 -> libcountm.so.2.0.0 libcountm.so.2.0.0 libcountm.so.0 -> libcountm.so.0.1.1 libcountm.so.0.1.1
However, when libcountm.so.0.1.1 is uninstalled (removed), a broken symlink libcountm.so.0 remains. It must be adjusted to point to libcountm.so.2.0.0. Otherwise, binaries with runtime NAME libcountm.so.0 will not load. Once the symlink points to libcountm.so.2.0.0, all binaries with runtime NAME libcountm.so.0 will use libcountm.so.2.0.0 versioned symbols, and run properly without any modification or relinking.

5.7  libcountm.h

The libcountm.h file contains the necessary code to version the symbols for building libcountm, and for compiling/linking with libcountm. During libcountm build, define LIBCOUNTM_BUILD. Otherwise, libcountm.h assumes the header file is being used to compile/link with another shared object or executable. Also, define DOVERSIONING during both building and compiling/link to use the symbol versioning. During the mod_countm build process, DOVERSIONING is defined inside of config.h, otherwise, a -DDOVERSIONING would have been added to CFALGS.

Chapter 6
Installing

6.1  RedHat, Fedora

6.1.1  RedHat, Fedora(i386): Installing

Verify the required rpms are installed and install any missing requirements.
rpm -i -test apache2-mod_countm-5.4-54_fc2.i386.rpm
Verify the server is not running.
/etc/rc.d/init.d/httpd status

If it is, then stop the server.
/etc/rc.d/init.d/httpd stop

Install the rpm.
rpm -i apache2-mod_countm-5.4-54_fc2.i386.rpm.i386.rpm
Adjusting /etc/httpd/conf.d/mod_countm.conf should not be necessary.
Restart the server.
/etc/rc.d/init.d/httpd restart

Automate httpd startup with:
chkconfig httpd on

See man mod_countm for more information.
See man countm for more information.

6.1.2  RedHat, Fedora (i386): Removing

rpm -e apache2-mod_countm

Due to the default nature of rpm -e, the database will not be deleted. An rm -rf /var/countm should be performed AFTER rpm -e to complete the removal.

6.2  FreeBSD 5.4 (i386): Installing

6.2.1  Package Dependencies

apache-2.0.50_3
autoconf-2.59_2
gmake-3.80_1
gd-2.0.25_1,1
png-1.2.6
db42-4.2.52_3
freetype2-2.1.7_3
jpeg-6b_3

6.2.2  FreeBSD 5.4 (i386): Installing From Package

The package is specific to 5.4-RELEASE/i686. It may (or may not) install properly for other releases. Root developer access required for other releases if testing required.
pkg_add mod_countm-5.4_1.tbz
Installs the prebuilt binary package into a FreeBSD 5.4-RELEASE i386 system.
pkg_delete mod_countm-5.4_1
Will delete the package. When the package is deleted, all information is erased, including the test/countm directory, the dbase directory, the bgimage directory, and the .conf file. Be certain to backup any important information prior to package removal.

6.2.3  FreeBSD 5.4 (i386): Installing From Port

The port is specific to 5.4-RELEASE/i686. It may (or may not) install properly for other releases. Root developer access required for other releases if testing required.
#cp mod_countm-5.4.tar.gz /usr/ports/distfiles
#cd /usr/ports/distfiles
#tar -xzpf mod_countm-5.4.tar.gz
#cd mod_countm-5.4
#cd dist/freebsd/port
#mkdir /usr/ports/www/mod_countm-5.4
#cp * /usr/ports/www/mod_countm-5.4
#cd /usr/ports/www/mod_countm-5.4
#make makesum
#make
#make install
#make deinstall
#make clean
Due to Apache apxs issues, the FreeBSD make step builds AND installs the module. The make install step installs the configuration files, the example/test html files, and the runtime font.
The automatic package scripts assume the apache2 httpd server default install location which implies that the httpd.conf file has an Include etc/apache2/Includes/*.conf statement. The mod_countm.conf file that is installed into etc/apache2/Includes will automatically be included.

6.3  Installing - OpenSolaris

The OpenSolaris package is built on a i386/Pentium II machine using Studio 11 (cc), SFWgcc34 (gcc, libgcc_s.so) and SFW/SUNW components. See the dist/solaris/depend file for more information.
Unpack the binary package into a temporary directory. A SFWcountm package directory will be created. Add the package to your system (as root) using:
#pkgadd -d `pwd` SFWcountm
Once added, restart the Apache2 server
#svcadm -v enable svc:/network/http:apache2
#svcadm -v restart svc:/network/http:apache2
See http://localhost/server-info/ for default mod_countm.conf settings.

6.4  mod_status and mod_cachem integration

The total number of requests mod_countm has handled and the total number of request mod_countm has handled since the last status request is the information displayed.
Mod_countm, if COUNTM_BDB is NOT defined, uses less than 32 bytes of mod_cachem shared memory cache.
If COUNTM_BDB is defined at compile time, mod_countm uses additional mod_cachem bytes, with the maximum being calculated as follows; For each process (normally StartServers + 1): two times the string length of each environment name, plus, the string length of each database name, plus, sizeof(cachem_bptr_t) times ( number environments plus number of database names), plus, about 11.
Assuming normal environment file path specifications averaging about 32 characters, and normal database names averaging about 16 characters: ( 2 * COUNTM_BDB_MAX_ENV * 32 + COUNTM_BDB_MAX_DB * 16) * ( StartServers + 1 ) + ( COUNTM_BDB_MAX_ENV + COUNTM_BDB_MAX_DB ) * sizeof(cachem_bptr_t) + 11 * ( StartServers + 1 ). 16384 for the default setting should be about right.
If COUNTM_BDB is defined at compile time, a listing of all BDB environments and all BDB environment/ databases opened by each process is displayed. For the environments, the flags bits are displayed in hex, and interpreted as follows:
bit 0 (LSB) = The environment was joined.
bit 1 = The environment was closed.
bit 2 = The environment was recovered.
bit 3 = The environment was deleted.
bit 4 = The environment was created.
Question:
Some status requests do not display any opened environments and databases for a thread/process, even when the previous status request displayed both for a specific pid.
Answer:
The process probably terminated, either due to MaxRequestsPerChild being exceeded, or due to a restart. All environments and databases opened by an process are closed on process termination.

6.5  libgd

See section "What's new in version 2.0.16" from the gd manual for more information. Any Apache 2 Multi-Processing Module using threads (worker, etc) requires libgd >= 2.0.16 and the compile time option COUNTM_FORCE_LIBGD_THREADSAFE set to 1. If an Ünable to find gdFontCacheSetup" error at httpd startup is presented, then COUNTM_FORCE_LIBGD_THREADSAFE is 1, and libgd < 2.0.16.
For Redhat 9.0 and Fedora Core 1, which uses gd 1.8.4 and gd 2.0.15 respectively, COUNTM_FORCE_LIBGD_THREADSAFE should be 0. The default prefork MPM will work properly. The worker MPM will function properly, but subject to the restrictions stated in the gd manual.

6.6  libcountm

The build process creates libcountm. Functions common to both mod_countm and countm are placed into libcountm. This library is intended only for use by the package and does not export any specific programming API interface. See the libcountm chapter for more info.

6.7  Building Release_X_Y from .tar.gz distribution

6.7.1  requirements

mod_cachem (sourceforge.net/projects/cachem)
gd
libjpeg
libfreetype
libpng
One of:
DB4 (www.sleepycat.com)
MySQL (www.mysql.com)
optional: doxygen
latex
tth

6.7.2  ./configure variables

The following is a list of recognized environmental variables (Case is significant):
DIRNAME
The name and location of 'dirname' program. Defaults to 'dirname'.
BASENAME
The name and location of 'basename' program. Defaults to 'basename'.
ID
The name and location of the 'id' program. Defaults to 'id'.
APXS_CFLAGS
These flags are added to the APXS command line AND CFLAGS. Only valid APXS AND C compiler options are allowed. See man apxs for more info. To determine the flags being added to the apxs portion of the build, use /path/to/apxs -q CFLAGS. These are usually the -I -l -L options used to locate libraries and include files in non system standard locations. These options are added to the APXS command line and to CFLAGS.
CFLAGS
Usually preset by the build tools, and does not need to be modified.
LDFLAGS
Used by configure to locate libraries, then passed to apxs. See man apxs for valid flags (usually only -L and -Wl are valid).
LIBS
Added to by configure, then passed to apxs. Usually only -l allowed.
LIBCOUNTM_LIBS
libcountm only requires a subset of the mod_countm and countm libraries. If LIBS is empty, the initial contents of LIBCOUNTM_LIBS is empty. If LIBS is not empty, the initial contents of LIBCOUNTM_LIBS is LIBS. Added to by configure, then passed to countm build process. Currently, it requires no libraries.
COUNTM_LIBS
The countm utility only requires a subset of the mod_countm libraries. If LIBS is empty, the initial contents of COUNTM_LIBS is empty. If LIBS is not empty, the initial contents of COUNTM_LIBS is LIBS. Added to by configure, then passed to countm build process.
MOD_COUNTM_RELEASE
FreeBSD packages:"_$PORTREVISION". RPM packages:"-%release". Default:".tar.gz".
NEEDWL
A hack for including the libcountm library into the mod_countm build. Some version require NEEDWL="-Wl,". Some version require NEEDWL="" .
docdir
The install location for the documentation (if built). Defaults to $(prefix)/doc/$MOD_COUNTM_PACKAGE-$MOD_COUNTM_VERSION. Any value given will be relative to $(prefix). If a trailing / is added, then $MOD_COUNTM_PACKAGE-$MOD_COUNTM_VERSION is appended to docdir. If a leading / is not given, then assumed to be relative to prefix.
htmldir
The install location for supporting html files.
APACHE_UID
Apache runtime user id. See the Apache configuration directive user.
APACHE_GID
Apache runtime group id. See the Apache configuration directive group.
NOTE
If APACHE_GID and APACHE_UID are not given on the command line, and id is available, then use id to get APACHE_GID and APACHE_UID. Otherwise, configure fails.

6.7.3  ./configure command line options

The following is a list of recognized ./configure command options:
-libdir
The install location for libcountm.
-mandir
The install location for mod_countm.1 and countm.1 man pages.
-sbindir
The install location for the countm utility binary.
-libexecdir
The install location for the Apache2 DSO module. Normally automatically set via apxs during configure.
-localstatedir
The install location for the DSO module support files. Normally automatically set via apxs during configure.
-sysconfdir
The install location of mod_countm.conf DSO config file. Normally automatically set via apxs during configure.
-with-apxs
The executable name and location of the apxs utility.
-with-db
The name of the db4 library.
-with-gd
The name of the gd library.
-with-jpeg
The name of the jpeg library.
-with-freetype
The name of the freetype library.
-with-png
The name of the png library.
-with-latex
The path and name of the latex program. The tex docs are built only if latex program found.
-with-doxygen
The path and name of the doxygen program. The doxygen docs are built only if doxygen program found.
-with-texi2pdf
The path and name of the texi2pdf program. The texi2pdf docs are built only if texi2pdf program found.
-with-tth
The path and name of the [tth] program. The tth docs are built only if [tth] program found.
-enable-versioning
Set to yes to build a versioned libcountm. Use -disable-versioning to force a nonversioned build.

6.7.4  building

Building in a separate directory using the configure script from the .tar.gz distribution is recommended and fully supported.
For mod_countm, use APXS_CFLAGS to inform configure of libraries, include files, and library locations. Because of the build process, APXS_CFLAGS is added to CFLAGS. For many system builds, adjusting CFLAGS should not be necessary.
Using ./path/to/configure -help will list some additional information.
Comments in configure.ac are a good source of information.
After configure, the usual
make
make install

will build and install the module.
Mod_countm supports DESTDIR as part of the install process if, and only if, the platform instdso.sh script supports DESTDIR.

6.8  Building CURRENT_X_Y From Source

The cvs repository is arranged in Current/Release pattern, with the most recent release as the highest revisions on the main trunk. A cvs checkout using the default tag will always checkout the most recent release. The next release is developed along a Current branch, then merged into main as a release. Branch tags are alway Current_X_Y, and release tags are always on the main trunk, and are Release_X_Y.
The mod_countm CVS repository files and the latest release distribution file should allow Current_X_Y to be built from source. First, download Release_X_Y from the project site and unpack the distribution. Then, rename the top directory from mod_countm-X.Y to mod_countm-A.B, where A.B is the Current_A_B version. Checkout the Current_A_B from the repository directly into the mod_countm-A.B directory.
The following example assumes the latest release is mod_countm-5.0 (Release_5_0), and the current version is Current_5_1, using a BASH shell.
tar -xzpf mod_countm-5.0.tar.gz
mv mod_countm-5.0 mod_countm-5.1
CVSROOT=:pserver:anonymous@cvs.sourceforge.net:/cvsroot/countm
export CVSROOT
cvs login
password:<just hit enter>
cvs co -r CURRENT_5_1 -d mod_countm-5.1 countm

6.9  Apache2 apxs

6.9.1  building libcountm

The libcountm.so library must be built, and installed, prior to building the module. In the following example, if /lib/install/directory is a system library path, then -rpath may be omitted.
libtool gcc -I./ -c libcountm.c
libtool gcc -rpath /lib/install/directory -o libcountm.la libcountm.lo
libtool cp libcountm.la /lib/install/directory

6.9.2  building mod_countm

To build the module directly using apxs, specify the libraries (including libcountm), the library locations, and the other parameters. After building, see mod_countm.conf.in for configuration directives and handler information.
apxs -c -i -Wc,-g -DVERSION=5.4-custom -Wl,-lpng -Wl,-lgd, -Wl,-lm -Wl,-ljpeg -Wl,-ldb -Wl,-lcountm -DCOUNTM_FORCE_LIBGD_THREADSAFE=1 mod_countm.c version.c
Create any database environment directories, the fonts directories, the lockfile directories, and the background images directories. The access permissions must be set so httpd can access them and create files within them at runtime. Install true-type fonts into the CountmFontDir directory or set GDFONTPATH, and install the background images into the background image directories. Add a configuration to the httpd config file (usually httpd.conf).

6.10  Created/ Installed Files

Assuming a default FC2 installation defining only a global server:
/usr/lib/libcountm.so
/usr/include/libcountm.h
/usr/sbin/countm
/usr/lib/httpd/modules/mod_countm.so
/etc/httpd/conf.d/mod_countm.conf
/var/countm/fonts/FreeMono.ttf
/var/countm/dbase
/var/countm/bgfiles/ss.jpeg
/usr/share/man/man1/mod_countm.1
/usr/share/man/man1/countm.1
/var/www/html/test/countm/ex*.html

Files created at runtime depend on server configuration, but defaults are:
/var/countm/dbase/* (various db4 database files)
/var/countm/countm.lock (intermittent, if AcceptMutex=Lockfile)

6.11  RedHat 9 i586 Systems

See bugzilla.redhat.com #86381, #88456 for a clear concise explanation of what follows.
RH9 ships with a Berkeley DB4 library that relies on the kernel or glibc support for NPTL. The i586 version of glibc does not have NPTL support. The "function not implemented error" is not a problem with countm, but affects countm.
Try compiling and running the create.c program on your system. It compiled and ran without error on my old RH9 single processor i686 development system, compiled and ran on my old RH9 SMP PII system, and compiles and runs without error on the same hardware now running Fedora Yarrow. However, it runs with errors on all RH9 non i686 single processor hardware.
As a recommendation, install the latest kernel, the latest glibc and associated packages, and the most recent httpd. The semaphore lock method may be used with versions above 2.0.40-21.9, but there may be some semaphore cleanup problems. They may be downloaded from ftp.redhat.com/pub/redhat/linux/updates/9/en/os. The best method is to download up2date-3.1.23.2-1.i386.rpm, and up2date-gnome-3.1.23.2-1.i386.rpm, then install them with: rpm -Fvh up2date-3.1.23.2-1.i386.rpm up2date-gnome-3.1.23.2-1.i386.rpm Run up2date, be sure to set the preferences to update the kernel also, and update your system. See rhn.redhat.com/errata/RHSA-2003-267.html for more info.
To solve the error, a nonptl version of db4 must be installed. Applying the following patch to db4.spec from db-4.0.14-20.src.rpm, and rebuilding with rpmbuild -ba db4.spec will create the nonptl rpms.
Replace the default db4 nptl packages with the new db4 nonptl packages.
rpm -Fvh <Build RPMS>
Install the apache2-mod_countm-5.4-54_rh9i586.i586.rpm package.
mod_countm will now run without the function not implemented error.

6.11.1  Disclaimer

Unknown is the impact of installing the nonptl version of DB4 onto the i586 system. If you decide not to keep the newly installed nonptl db4 package, then you will need to use -oldpackage when reFreshing the default distribution rpms.

6.11.2  Default RH9 NPTL Packages

db4-java-4.0.14-20
db4-4.0.14-20
db4-utils-4.0.14-20
db4-devel-4.0.14-20

6.11.3  Default Installed RPMS

SRPMS/db4-4.0.14-20.src.rpm
RPMS/i386/db4-4.0.14-20.i386.rpm
RPMS/i386/db4-utils-4.0.14-20.i386.rpm
RPMS/i386/db4-devel-4.0.14-20.i386.rpm
RPMS/i386/db4-java-4.0.14-20.i386.rpm
RPMS/i386/db4-debuginfo-4.0.14-20.i386.rpm

6.11.4  Patched db4.spec Created RPMS

SRPMS/db4-4.0.14-21.src.rpm RPMS/i586/db4-4.0.14-21.i586.rpm RPMS/i586/db4-utils-4.0.14-21.i586.rpm RPMS/i586/db4-devel-4.0.14-21.i586.rpm RPMS/i586/db4-java-4.0.14-21.i586.rpm RPMS/i586/db4-debuginfo-4.0.14-21.i586.rpm

6.11.5  db.spec Patch

To install the patch, use:
cp db4.spec.patch /usr/src/redhat/SPECS
patch -p0 < db4.spec.patch

BEGIN db4.spec.patch
*** db4.spec.orig	2003-02-05 13:01:35.000000000 -0800
--- db4.spec	2003-12-15 08:24:26.000000000 -0800
***************
*** 1,5 ****
  %define java_arches %{ix86} alpha ia64 ppc s390 s390x
! %define nptl_arches %{ix86}
  
  # compatibility with legacy versions of rpm
  %{!?_lib:%define _lib	lib}
--- 1,5 ----
  %define java_arches %{ix86} alpha ia64 ppc s390 s390x
! %define nptl_arches %nil
  
  # compatibility with legacy versions of rpm
  %{!?_lib:%define _lib	lib}
***************
*** 11,17 ****
  Summary: The Berkeley DB database library (version 4) for C.
  Name: db4
  Version: 4.0.14
! Release: 20
  Source: http://www.sleepycat.com/update/%{version}/db-%{version}.tar.gz
  Source1: http://www.sleepycat.com/update/1.85/db.1.85.tar.gz
  Patch10: http://www.sleepycat.com/update/1.85/patch.1.1
--- 11,17 ----
  Summary: The Berkeley DB database library (version 4) for C.
  Name: db4
  Version: 4.0.14
! Release: 21
  Source: http://www.sleepycat.com/update/%{version}/db-%{version}.tar.gz
  Source1: http://www.sleepycat.com/update/1.85/db.1.85.tar.gz
  Patch10: http://www.sleepycat.com/update/1.85/patch.1.1
***************
*** 31,36 ****
--- 31,37 ----
  BuildPreReq: jdkgcj >= 0.1.0
  %endif
  BuildRoot: %{_tmppath}/%{name}-root
+ BuildArchitectures: i586
  
  %description
  The Berkeley Database (Berkeley DB) is a programmatic toolkit that
***************
*** 141,146 ****
--- 142,148 ----
  set -x	# XXX painful to watch
  
  %build
+ export RPM_OPT_FLAGS=`echo $RPM_OPT_FLAGS | sed 's/i686/i586/'`
  CFLAGS="$RPM_OPT_FLAGS"; export CFLAGS
  
  # Static link with old db-185 libraries.
END db4.spec.patch

6.11.6  Test Program

BEGIN create.c
/* simple test program to test for error */
/* just about verbatim from the tutorial */
/* gcc -DCWD=\"`pwd`\" -o db4test -ldb create.c */

#include <stdio.h>
#include <db.h>

#ifndef CWD
#define CWD "/home/bkyoung/proj/test/dbase"
#endif

DB_ENV *
db_setup(home, data_dir, errfp, progname)
     char *home, *data_dir, *progname;
     FILE *errfp;
{
  DB_ENV *dbenv;
  int ret;

  /*
   * Create an environment and initialize it for additional error
   * reporting.
   */
  if ((ret = db_env_create(&dbenv, 0)) != 0) {
    fprintf(errfp, "%s: %s\n", progname, db_strerror(ret));
    return (NULL);
  }
  dbenv->set_errfile(dbenv, errfp);
  dbenv->set_errpfx(dbenv, progname);

        /*
         * Specify the shared memory buffer pool cachesize: 5MB.
         * Databases are in a subdirectory of the environment home.
         */
  if ((ret = dbenv->set_cachesize(dbenv, 0, 5 * 1024 * 1024, 0)) != 0) {
    dbenv->err(dbenv, ret, "set_cachesize");
    goto err;
  }
  if ((ret = dbenv->set_data_dir(dbenv, data_dir)) != 0) {
    dbenv->err(dbenv, ret, "set_data_dir: %s", data_dir);
    goto err;
  }

  /* Open the environment with full transactional support. */
  if ((ret = dbenv->open(dbenv, home, DB_CREATE |
             DB_INIT_LOG | DB_INIT_LOCK | DB_INIT_MPOOL | DB_INIT_TXN, 0)) != 0)
    {
      dbenv->err(dbenv, ret, "environment open: %s", home);
      goto err;
    }

  return (dbenv);

 err:    (void)dbenv->close(dbenv, 0);
  return (NULL);
}

int
main(int argc, char * argv[], char * envp[])
{
  DB_ENV * dbenv;

  dbenv = db_setup(CWD,CWD, NULL, argv[0]);
  if (dbenv !=NULL)
     (void)dbenv->close(dbenv, 0);

  return 0;
}

END create.c

Chapter 7
Project Information

7.1  TO DO

7.2  Project Status

The project is transitioning to stable.
The format of DB_ACCESS is stable.
The format of DB_COUNTER is stable.
FC2 RPMS are available for download from sourceforge project site.
A FreeBSD 5.4-RELEASE port is available.

7.3  Supported Distributions

Fedora Core 4 () i386 Linux/Apache 2.0.48
FreeBSD i386 5.4-RELEASE

7.4  Targeted Audience

As a simple page counter, the project is intended for small office/ home office system administrators anticipating low volume web traffic and interested in adding page counter capabilities to their Apache 2 server.

7.5  sourceforge.net Information

Development Status: 5-Stable/production
Operating System: POSIX: Linux
Topic: Internet: WWW/HTTP: Dynamic Content: Page Counters
Intended Audience: Other Audience
License: OSI Approved: BSD License
Programming Language: C
Environment: Web Environment
Natural Language: English
Project Unix Name: countm

7.6  Release Distribution Files

Release 5.4 (Release_5_4)
apache2-mod_countm-5.4-54.fc2.src.rpm
apache2-mod_countm-5.4-54.fc2.i386.rpm
apache2-mod_countm-debuginfo-5.4-54.fc2.i386.rpm
apache2-mod_countm-5.4-54.9.src.rpm
apache2-mod_countm-5.4-54.9.i686.rpm
apache2-mod_countm-debuginfo-5.4-54.9.i686.rpm
apache2-mod_countm-5.4-54.9.i586.rpm
apache2-mod_countm-debuginfo-5.4-54.9.i586.rpm
mod_countm-5.4_1.tbz
mod_countm-5.4.tar.gz

7.7  Credits

Adapted to Apache 2 by <Byron Young> spamiccling@yahoo.com, bkyoung@users.sourceforge.net
Adapted from mod_ometer by J Craig. See modules.apache.org for more information.
Image source http://www.superform-aluminium.com/news/Photo%20Gallery/Gallery%20-%20applications/Resources/spacestation.jpeg
FreeMono.ttf is from the freefont project.

Chapter 8
Debugging

The following are specific to Fedora Core 2, gcc-3.3.2, gdb-6.0post. The rpmbuild process creates apache2-mod_countm-debuginfo-5.4-54_fc2.i386.rpm. This package contains the debug information for the apaceh2-mod_countm-5.4-54_fc2.i386.rpm package. The apaceh2-mod_countm-5.4-54_fc2.i386.rpm package object files are stripped. After installing the deguginfo package, the mod_countm.so may be debugged using gdb. The following is not the best method for debugging, but gets the job done.

8.1  Download debuginfo Package

Either figure out which deguginfo files you will need (at least httpd-debuginfo), or download all debuginfo files from download.fedora.redhat.com/pub/fedora/linux/core/2/i386/debug and install them. To debug the module, download apache2-mod_countm-debuginfo-5.4-54_fc2.i386.rpm.

8.2  Prelink httpd Executable

The default build from httpd.spec creates pie httpd. In order to use gdb to debug it, it must be prelinked with prelink.
/usr/sbin/prelink /usr/sbin/httpd

Also, the directory /lib/tls was added to /etc/prelink.conf These should be run as root, so the cache file may be updated properly.
[root]objdump -f /usr/sbin/httpd
/usr/sbin/httpd:     file format elf32-i386
architecture: i386, flags 0x00000150:
HAS_SYMS, DYNAMIC, D_PAGED
start address 0x0000eda0
              {---------} => NOT PRELINKED!!
[root]/usr/sbin/prelink /usr/sbin/httpd
[root]objdump -f /usr/sbin/httpd
/usr/sbin/httpd:     file format elf32-i386
architecture: i386, flags 0x00000150:
HAS_SYMS, DYNAMIC, D_PAGED
start address 0x0200eda0
              {---------} => PRELINKED!!

The start address in this example is 0x0200eda0

8.3  Preload mod_countm.so

(BASH/fc2)
LD_PRELOAD=/usr/lib/httpd/modules/mod_countm.so:libaprutil-0.so.0:libapr-0.so.0
export LD_PRELOAD
(CSH/FreeBSD)
setenv LD_PRELOAD /usr/local/libexec/apache2/mod_countm.so:/usr/local/lib/apache2/libapr-0.so.9:/usr/local/lib/apache2/libaprutil-0.so.9

8.4  A gdb session

[root]# gdb /usr/sbin/httpd
GNU gdb Red Hat Linux (6.0post-0.20031117.7rh)
Copyright 2003 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i386-redhat-linux-gnu"...Using host libthread_db library "/lib/tls/libthread_db.so.1".

(gdb) add-symbol-file /usr/sbin/httpd 0x200eda0 -readnow
add symbol table from file "/usr/sbin/httpd" at
	.text_addr = 0x200eda0
(y or n) y
Reading symbols from /usr/sbin/httpd...expanding to full symbols...Reading symbols from /usr/lib/debug//usr/sbin/httpd.debug...expanding to full symbols...done.
done.
(gdb) b main

Breakpoint 1 at 0x201d155: file /usr/src/debug/httpd-2.0.48/server/main.c, line 443.
(gdb) r -X
Starting program: /usr/sbin/httpd -X
setpgrp failed in child: No such process
[Thread debugging using libthread_db enabled]
[New Thread -1207136128 (LWP 7939)]
[Switching to Thread -1207136128 (LWP 7939)]

Breakpoint 1, main (argc=2, argv=0xbff8ccc4)
    at /usr/src/debug/httpd-2.0.48/server/main.c:443
443	    ap_server_pre_read_config  = apr_array_make(pcommands, 1, sizeof(char *));
(gdb) info shared
From        To          Syms Read   Shared Object Library
0x007f41c0  0x007f7078  Yes         /usr/lib/httpd/modules/mod_countm.so
0x00511820  0x00534740  Yes         /lib/libssl.so.4
0x00380aa0  0x0041ac3c  Yes         /lib/libcrypto.so.4
0x00345e00  0x00351eb0  Yes         /usr/lib/libgssapi_krb5.so.2
0x002ce850  0x0031e89c  Yes         /usr/lib/libkrb5.so.3
0x00296a90  0x002971dc  Yes         /lib/libcom_err.so.2
0x0029e4e0  0x002b3e40  Yes         /usr/lib/libk5crypto.so.3
0x00d2d740  0x00d37f30  Yes         /lib/libresolv.so.2
0x00cf65d0  0x00d001f8  Yes         /usr/lib/libz.so.1
0x0053fcb0  0x0054bb34  Yes         /lib/libpcre.so.0
0x00a88a90  0x00a88f58  Yes         /usr/lib/libpcreposix.so.0
0x00c61e10  0x00c6ffb4  Yes         /usr/lib/libaprutil-0.so.0
0x0082d890  0x00850930  Yes         /usr/lib/libldap.so.2
0x00de45e0  0x00debbac  Yes         /usr/lib/liblber.so.2
0x00c16430  0x00c19edc  Yes         /usr/lib/libgdbm.so.2
0x00935ca0  0x009e0280  Yes         /lib/tls/libdb-4.2.so
0x00dc2110  0x00dd7de0  Yes         /usr/lib/libexpat.so.0
0x0044da70  0x00459a08  Yes         /lib/libnsl.so.1
0x00c7c630  0x00c90d4c  Yes         /usr/lib/libapr-0.so.0
0x004cacb0  0x004d0954  Yes         /lib/tls/librt.so.1
0x00bed300  0x00c04c4c  Yes         /lib/tls/libm.so.6
0x004907e0  0x004930a4  Yes         /lib/libcrypt.so.1
0x00d1c160  0x00d23a9c  Yes         /lib/tls/libpthread.so.0
0x00c0fcd0  0x00c10b60  Yes         /lib/libdl.so.2
0x00ac41c0  0x00bc3570  Yes         /lib/tls/libc.so.6
0x004709e0  0x00489cd4  Yes         /usr/lib/libpng12.so.0
0x001151b0  0x00124818  Yes         /usr/lib/libgd.so.2
0x002264d0  0x0023ec5c  Yes         /usr/lib/libjpeg.so.62
0x00d9e070  0x00dabc40  Yes         /usr/lib/libsasl2.so.2
0x00a92a50  0x00aa4207  Yes         /lib/ld-linux.so.2
0x00811210  0x0081bf74  Yes         /usr/X11R6/lib/libXpm.so.4
0x00560290  0x005d0bb0  Yes         /usr/X11R6/lib/libX11.so.6
0x00157280  0x00195754  Yes         /usr/lib/libfreetype.so.6
0x00d0a6d0  0x00d14178  Yes         /usr/X11R6/lib/libXext.so.6
(gdb) b countm_method_handler
Breakpoint 2 at 0x7f5266: file src/mod_countm.c, line 1129.
(gdb) c
Continuing.

Breakpoint 2, countm_method_handler (r=0x99311dc) at src/mod_countm.c:1129
1129	  struct sembuf op_lock[2] =
(gdb) quit
The program is running.  Exit anyway? (y or n) y
[root]# exit

8.5  Debugging the threaded MPMs

Use the gdb attach process to debug the Worker MPM (threads). Set the Apache2 configuraion directives StartServers to 1, MaxClients and ThreadsPerChild set to 4. All requests will be handled by the one child process. Setting MaxRequestsPerChild to 4 will restart the child server often, allowing debugging of process cleanup and process creation code.
[root@waiter mod_countm-5.3]# /etc/rc.d/init.d/httpd start
Starting httpd:                                 [OK]
[root@waiter mod_countm-5.3]# ps aux | grep httpd
root     22796  0.0  5.9 32772 15140 ?       S    12:58   0:01 /usr/sbin/httpd
apache   22799  0.0  5.9 94368 15280 ?       S    12:58   0:00 /usr/sbin/httpd
root     22807  0.0  0.2  4572  596 pts/4    S    12:58   0:00 grep httpd
[root@waiter mod_countm-5.3]# gdb /usr/sbin/httpd 22799
GNU gdb Red Hat Linux (6.0post-0.20040223.19rh)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i386-redhat-linux-gnu"...Using host libthread_db library "/lib/tls/libthread_db.so.1".

Attaching to program: /usr/sbin/httpd, process 22799
Error while mapping shared library sections:
: Success.
Error while reading shared library symbols:
: No such file or directory.
Reading symbols from /lib/libpcre.so.0...Reading symbols from /usr/lib/debug//lib/libpcre.so.0.0.1.debug...done.
done.
Loaded symbols for /lib/libpcre.so.0
Reading symbols from /usr/lib/libpcreposix.so.0...Reading symbols from /usr/lib/debug//usr/lib/libpcreposix.so.0.0.0.debug...done.
done.
Loaded symbols for /usr/lib/libpcreposix.so.0
Reading symbols from /usr/lib/libaprutil-0.so.0...done.
Loaded symbols for /usr/lib/libaprutil-0.so.0
Reading symbols from /usr/lib/libldap.so.2...done.
Loaded symbols for /usr/lib/libldap.so.2
Reading symbols from /usr/lib/liblber.so.2...done.
Loaded symbols for /usr/lib/liblber.so.2
Reading symbols from /lib/tls/libdb-4.2.so...done.
Loaded symbols for /lib/tls/libdb-4.2.so
Reading symbols from /usr/lib/libexpat.so.0...done.
Loaded symbols for /usr/lib/libexpat.so.0
Reading symbols from /usr/lib/libapr-0.so.0...done.
Loaded symbols for /usr/lib/libapr-0.so.0
Reading symbols from /lib/tls/librt.so.1...Reading symbols from /usr/lib/debug//lib/tls/librt-2.3.3.so.debug...done.
done.
Loaded symbols for /lib/tls/librt.so.1
Reading symbols from /lib/tls/libm.so.6...Reading symbols from /usr/lib/debug//lib/tls/libm-2.3.3.so.debug...done.
done.
Loaded symbols for /lib/tls/libm.so.6
Reading symbols from /lib/libcrypt.so.1...Reading symbols from /usr/lib/debug//lib/libcrypt-2.3.3.so.debug...done.
done.
Loaded symbols for /lib/libcrypt.so.1
Reading symbols from /lib/tls/libpthread.so.0...Reading symbols from /usr/lib/debug//lib/tls/libpthread-0.61.so.debug...done.
[Thread debugging using libthread_db enabled]
[New Thread -150441856 (LWP 22799)]
[New Thread -211182672 (LWP 22805)]
[New Thread -200692816 (LWP 22804)]
[New Thread -190202960 (LWP 22803)]
[New Thread -179713104 (LWP 22802)]
[New Thread -169223248 (LWP 22801)]
done.
Loaded symbols for /lib/tls/libpthread.so.0
Reading symbols from /lib/libdl.so.2...Reading symbols from /usr/lib/debug//lib/libdl-2.3.3.so.debug...done.
done.
Loaded symbols for /lib/libdl.so.2
Reading symbols from /lib/tls/libc.so.6...Reading symbols from /usr/lib/debug//lib/tls/libc-2.3.3.so.debug...done.
done.
Loaded symbols for /lib/tls/libc.so.6
Reading symbols from /lib/libresolv.so.2...Reading symbols from /usr/lib/debug//lib/libresolv-2.3.3.so.debug...done.
done.
Loaded symbols for /lib/libresolv.so.2
Reading symbols from /usr/lib/libsasl2.so.2...done.
Loaded symbols for /usr/lib/libsasl2.so.2
Reading symbols from /lib/libssl.so.4...done.
Loaded symbols for /lib/libssl.so.4
Reading symbols from /lib/libcrypto.so.4...done.
Loaded symbols for /lib/libcrypto.so.4
Reading symbols from /lib/ld-linux.so.2...Reading symbols from /usr/lib/debug//lib/ld-2.3.3.so.debug...done.
done.
Loaded symbols for /lib/ld-linux.so.2
Reading symbols from /usr/lib/libgssapi_krb5.so.2...done.
Loaded symbols for /usr/lib/libgssapi_krb5.so.2
Reading symbols from /usr/lib/libkrb5.so.3...done.
Loaded symbols for /usr/lib/libkrb5.so.3
Reading symbols from /lib/libcom_err.so.2...done.
Loaded symbols for /lib/libcom_err.so.2
Reading symbols from /usr/lib/libk5crypto.so.3...done.
Loaded symbols for /usr/lib/libk5crypto.so.3
Reading symbols from /usr/lib/libz.so.1...done.
Loaded symbols for /usr/lib/libz.so.1
Reading symbols from /lib/libnss_files.so.2...Reading symbols from /usr/lib/debug//lib/libnss_files-2.3.3.so.debug...done.
done.
Loaded symbols for /lib/libnss_files.so.2
Reading symbols from /etc/httpd/modules/mod_access.so...Reading symbols from /usr/lib/debug//usr/lib/httpd/modules/mod_access.so.debug...done.
done.
Loaded symbols for /etc/httpd/modules/mod_access.so
Reading symbols from /etc/httpd/modules/mod_auth.so...Reading symbols from /usr/lib/debug//usr/lib/httpd/modules/mod_auth.so.debug...done.
done.
Loaded symbols for /etc/httpd/modules/mod_auth.so
Reading symbols from /etc/httpd/modules/mod_auth_anon.so...Reading symbols from /usr/lib/debug//usr/lib/httpd/modules/mod_auth_anon.so.debug...done.
done.
Loaded symbols for /etc/httpd/modules/mod_auth_anon.so
Reading symbols from /etc/httpd/modules/mod_auth_dbm.so...Reading symbols from /usr/lib/debug//usr/lib/httpd/modules/mod_auth_dbm.so.debug...done.
done.
Loaded symbols for /etc/httpd/modules/mod_auth_dbm.so
Reading symbols from /etc/httpd/modules/mod_auth_digest.so...Reading symbols from /usr/lib/debug//usr/lib/httpd/modules/mod_auth_digest.so.debug...done.
done.
Loaded symbols for /etc/httpd/modules/mod_auth_digest.so
Reading symbols from /etc/httpd/modules/mod_ldap.so...Reading symbols from /usr/lib/debug//usr/lib/httpd/modules/mod_ldap.so.debug...done.
done.
Loaded symbols for /etc/httpd/modules/mod_ldap.so
Reading symbols from /etc/httpd/modules/mod_auth_ldap.so...Reading symbols from /usr/lib/debug//usr/lib/httpd/modules/mod_auth_ldap.so.debug...done.
done.
Loaded symbols for /etc/httpd/modules/mod_auth_ldap.so
Reading symbols from /etc/httpd/modules/mod_include.so...Reading symbols from /usr/lib/debug//usr/lib/httpd/modules/mod_include.so.debug...done.
done.
Loaded symbols for /etc/httpd/modules/mod_include.so
Reading symbols from /etc/httpd/modules/mod_log_config.so...Reading symbols from /usr/lib/debug//usr/lib/httpd/modules/mod_log_config.so.debug...done.
done.
Loaded symbols for /etc/httpd/modules/mod_log_config.so
Reading symbols from /etc/httpd/modules/mod_env.so...Reading symbols from /usr/lib/debug//usr/lib/httpd/modules/mod_env.so.debug...done.
done.
Loaded symbols for /etc/httpd/modules/mod_env.so
Reading symbols from /etc/httpd/modules/mod_mime_magic.so...Reading symbols from /usr/lib/debug//usr/lib/httpd/modules/mod_mime_magic.so.debug...done.
done.
Loaded symbols for /etc/httpd/modules/mod_mime_magic.so
Reading symbols from /etc/httpd/modules/mod_cern_meta.so...Reading symbols from /usr/lib/debug//usr/lib/httpd/modules/mod_cern_meta.so.debug...done.
done.
Loaded symbols for /etc/httpd/modules/mod_cern_meta.so
Reading symbols from /etc/httpd/modules/mod_expires.so...Reading symbols from /usr/lib/debug//usr/lib/httpd/modules/mod_expires.so.debug...done.
done.
Loaded symbols for /etc/httpd/modules/mod_expires.so
Reading symbols from /etc/httpd/modules/mod_deflate.so...Reading symbols from /usr/lib/debug//usr/lib/httpd/modules/mod_deflate.so.debug...done.
done.
Loaded symbols for /etc/httpd/modules/mod_deflate.so
Reading symbols from /etc/httpd/modules/mod_headers.so...Reading symbols from /usr/lib/debug//usr/lib/httpd/modules/mod_headers.so.debug...done.
done.
Loaded symbols for /etc/httpd/modules/mod_headers.so
Reading symbols from /etc/httpd/modules/mod_usertrack.so...Reading symbols from /usr/lib/debug//usr/lib/httpd/modules/mod_usertrack.so.debug...done.
done.
Loaded symbols for /etc/httpd/modules/mod_usertrack.so
Reading symbols from /etc/httpd/modules/mod_setenvif.so...Reading symbols from /usr/lib/debug//usr/lib/httpd/modules/mod_setenvif.so.debug...done.
done.
Loaded symbols for /etc/httpd/modules/mod_setenvif.so
Reading symbols from /etc/httpd/modules/mod_mime.so...Reading symbols from /usr/lib/debug//usr/lib/httpd/modules/mod_mime.so.debug...done.
done.
Loaded symbols for /etc/httpd/modules/mod_mime.so
Reading symbols from /etc/httpd/modules/mod_dav.so...Reading symbols from /usr/lib/debug//usr/lib/httpd/modules/mod_dav.so.debug...done.
done.
Loaded symbols for /etc/httpd/modules/mod_dav.so
Reading symbols from /etc/httpd/modules/mod_status.so...Reading symbols from /usr/lib/debug//usr/lib/httpd/modules/mod_status.so.debug...done.
done.
Loaded symbols for /etc/httpd/modules/mod_status.so
Reading symbols from /etc/httpd/modules/mod_autoindex.so...Reading symbols from /usr/lib/debug//usr/lib/httpd/modules/mod_autoindex.so.debug...done.
done.
Loaded symbols for /etc/httpd/modules/mod_autoindex.so
Reading symbols from /etc/httpd/modules/mod_asis.so...Reading symbols from /usr/lib/debug//usr/lib/httpd/modules/mod_asis.so.debug...done.
done.
Loaded symbols for /etc/httpd/modules/mod_asis.so
Reading symbols from /etc/httpd/modules/mod_info.so...Reading symbols from /usr/lib/debug//usr/lib/httpd/modules/mod_info.so.debug...done.
done.
Loaded symbols for /etc/httpd/modules/mod_info.so
Reading symbols from /etc/httpd/modules/mod_dav_fs.so...Reading symbols from /usr/lib/debug//usr/lib/httpd/modules/mod_dav_fs.so.debug...done.
done.
Loaded symbols for /etc/httpd/modules/mod_dav_fs.so
Reading symbols from /etc/httpd/modules/mod_vhost_alias.so...Reading symbols from /usr/lib/debug//usr/lib/httpd/modules/mod_vhost_alias.so.debug...done.
done.
Loaded symbols for /etc/httpd/modules/mod_vhost_alias.so
Reading symbols from /etc/httpd/modules/mod_negotiation.so...Reading symbols from /usr/lib/debug//usr/lib/httpd/modules/mod_negotiation.so.debug...done.
done.
Loaded symbols for /etc/httpd/modules/mod_negotiation.so
Reading symbols from /etc/httpd/modules/mod_dir.so...Reading symbols from /usr/lib/debug//usr/lib/httpd/modules/mod_dir.so.debug...done.
done.
Loaded symbols for /etc/httpd/modules/mod_dir.so
Reading symbols from /etc/httpd/modules/mod_imap.so...Reading symbols from /usr/lib/debug//usr/lib/httpd/modules/mod_imap.so.debug...done.
done.
Loaded symbols for /etc/httpd/modules/mod_imap.so
Reading symbols from /etc/httpd/modules/mod_actions.so...Reading symbols from /usr/lib/debug//usr/lib/httpd/modules/mod_actions.so.debug...done.
done.
Loaded symbols for /etc/httpd/modules/mod_actions.so
Reading symbols from /etc/httpd/modules/mod_speling.so...Reading symbols from /usr/lib/debug//usr/lib/httpd/modules/mod_speling.so.debug...done.
done.
Loaded symbols for /etc/httpd/modules/mod_speling.so
Reading symbols from /etc/httpd/modules/mod_userdir.so...Reading symbols from /usr/lib/debug//usr/lib/httpd/modules/mod_userdir.so.debug...done.
done.
Loaded symbols for /etc/httpd/modules/mod_userdir.so
Reading symbols from /etc/httpd/modules/mod_alias.so...Reading symbols from /usr/lib/debug//usr/lib/httpd/modules/mod_alias.so.debug...done.
done.
Loaded symbols for /etc/httpd/modules/mod_alias.so
Reading symbols from /etc/httpd/modules/mod_rewrite.so...Reading symbols from /usr/lib/debug//usr/lib/httpd/modules/mod_rewrite.so.debug...done.
done.
Loaded symbols for /etc/httpd/modules/mod_rewrite.so
Reading symbols from /etc/httpd/modules/mod_proxy.so...Reading symbols from /usr/lib/debug//usr/lib/httpd/modules/mod_proxy.so.debug...done.
done.
Loaded symbols for /etc/httpd/modules/mod_proxy.so
Reading symbols from /etc/httpd/modules/mod_proxy_ftp.so...Reading symbols from /usr/lib/debug//usr/lib/httpd/modules/mod_proxy_ftp.so.debug...done.
done.
Loaded symbols for /etc/httpd/modules/mod_proxy_ftp.so
Reading symbols from /etc/httpd/modules/mod_proxy_http.so...Reading symbols from /usr/lib/debug//usr/lib/httpd/modules/mod_proxy_http.so.debug...done.
done.
Loaded symbols for /etc/httpd/modules/mod_proxy_http.so
Reading symbols from /etc/httpd/modules/mod_proxy_connect.so...Reading symbols from /usr/lib/debug//usr/lib/httpd/modules/mod_proxy_connect.so.debug...done.
done.
Loaded symbols for /etc/httpd/modules/mod_proxy_connect.so
Reading symbols from /etc/httpd/modules/mod_cache.so...Reading symbols from /usr/lib/debug//usr/lib/httpd/modules/mod_cache.so.debug...done.
done.
Loaded symbols for /etc/httpd/modules/mod_cache.so
Reading symbols from /etc/httpd/modules/mod_suexec.so...Reading symbols from /usr/lib/debug//usr/lib/httpd/modules/mod_suexec.so.debug...done.
done.
Loaded symbols for /etc/httpd/modules/mod_suexec.so
Reading symbols from /etc/httpd/modules/mod_disk_cache.so...Reading symbols from /usr/lib/debug//usr/lib/httpd/modules/mod_disk_cache.so.debug...done.
done.
Loaded symbols for /etc/httpd/modules/mod_disk_cache.so
Reading symbols from /etc/httpd/modules/mod_file_cache.so...Reading symbols from /usr/lib/debug//usr/lib/httpd/modules/mod_file_cache.so.debug...done.
done.
Loaded symbols for /etc/httpd/modules/mod_file_cache.so
Reading symbols from /etc/httpd/modules/mod_mem_cache.so...Reading symbols from /usr/lib/debug//usr/lib/httpd/modules/mod_mem_cache.so.debug...done.
done.
Loaded symbols for /etc/httpd/modules/mod_mem_cache.so
Reading symbols from /etc/httpd/modules/mod_cgi.so...Reading symbols from /usr/lib/debug//usr/lib/httpd/modules/mod_cgi.so.debug...done.
done.
Loaded symbols for /etc/httpd/modules/mod_cgi.so
Reading symbols from /etc/httpd/modules/mod_auth_kerb.so...done.
Loaded symbols for /etc/httpd/modules/mod_auth_kerb.so
Reading symbols from /etc/httpd/modules/mod_auth_mysql.so...done.
Loaded symbols for /etc/httpd/modules/mod_auth_mysql.so
Reading symbols from /usr/lib/mysql/libmysqlclient.so.10...done.
Loaded symbols for /usr/lib/mysql/libmysqlclient.so.10
Reading symbols from /lib/libnsl.so.1...Reading symbols from /usr/lib/debug//lib/libnsl-2.3.3.so.debug...done.
done.
Loaded symbols for /lib/libnsl.so.1
Reading symbols from /etc/httpd/modules/mod_auth_pgsql.so...done.
Loaded symbols for /etc/httpd/modules/mod_auth_pgsql.so
Reading symbols from /usr/lib/libpq.so.3...done.
Loaded symbols for /usr/lib/libpq.so.3
Reading symbols from /etc/httpd/modules/mod_jk2.so...done.
Loaded symbols for /etc/httpd/modules/mod_jk2.so
Reading symbols from /usr/lib/httpd/modules/mod_countm.so...Reading symbols from /usr/lib/debug//usr/lib/httpd/modules/mod_countm.so.debug...done.
done.
Loaded symbols for /usr/lib/httpd/modules/mod_countm.so
Reading symbols from /usr/lib/libpng12.so.0...done.
Loaded symbols for /usr/lib/libpng12.so.0
Reading symbols from /usr/lib/libfreetype.so.6...done.
Loaded symbols for /usr/lib/libfreetype.so.6
Reading symbols from /usr/lib/libjpeg.so.62...done.
Loaded symbols for /usr/lib/libjpeg.so.62
Reading symbols from /usr/lib/libgd.so.2...done.
Loaded symbols for /usr/lib/libgd.so.2
Reading symbols from /usr/lib/libcountm.so.0...Reading symbols from /usr/lib/debug//usr/lib/libcountm.so.0.0.1.debug...done.
done.
Loaded symbols for /usr/lib/libcountm.so.0
Reading symbols from /usr/X11R6/lib/libXpm.so.4...done.
Loaded symbols for /usr/X11R6/lib/libXpm.so.4
Reading symbols from /usr/X11R6/lib/libX11.so.6...done.
Loaded symbols for /usr/X11R6/lib/libX11.so.6
Reading symbols from /usr/X11R6/lib/libXext.so.6...done.
Loaded symbols for /usr/X11R6/lib/libXext.so.6
Reading symbols from /etc/httpd/modules/mod_fltr.so...done.
Loaded symbols for /etc/httpd/modules/mod_fltr.so
Reading symbols from /etc/httpd/modules/mod_hilitem.so...done.
Loaded symbols for /etc/httpd/modules/mod_hilitem.so
Reading symbols from /usr/lib/libxml2.so.2...Reading symbols from /usr/lib/debug//usr/lib/libxml2.so.2.6.8.debug...done.
done.
Loaded symbols for /usr/lib/libxml2.so.2
Reading symbols from /etc/httpd/modules/mod_iterate.so...done.
Loaded symbols for /etc/httpd/modules/mod_iterate.so
Reading symbols from /etc/httpd/modules/mod_searchm.so...done.
Loaded symbols for /etc/httpd/modules/mod_searchm.so
Reading symbols from /usr/lib/libswish-e.so.2...Reading symbols from /usr/lib/debug//usr/lib/libswish-e.so.2.0.0.debug...done.
done.
Loaded symbols for /usr/lib/libswish-e.so.2
Reading symbols from /etc/httpd/modules/mod_test.so...done.
Loaded symbols for /etc/httpd/modules/mod_test.so
Reading symbols from /etc/httpd/modules/mod_testing.so...done.
Loaded symbols for /etc/httpd/modules/mod_testing.so
Reading symbols from /etc/httpd/modules/mod_time.so...done.
Loaded symbols for /etc/httpd/modules/mod_time.so
Reading symbols from /etc/httpd/modules/mod_perl.so...done.
Loaded symbols for /etc/httpd/modules/mod_perl.so
Reading symbols from /usr/lib/perl5/5.8.3/i386-linux-thread-multi/CORE/libperl.so...done.
Loaded symbols for /usr/lib/perl5/5.8.3/i386-linux-thread-multi/CORE/libperl.so
Reading symbols from /lib/libutil.so.1...Reading symbols from /usr/lib/debug//lib/libutil-2.3.3.so.debug...done.
done.
Loaded symbols for /lib/libutil.so.1
Reading symbols from /etc/httpd/modules/libphp5.so...Reading symbols from /usr/lib/debug//usr/lib/httpd/modules/libphp5.so.debug...done.
done.
Loaded symbols for /etc/httpd/modules/libphp5.so
Reading symbols from /usr/lib/libpspell.so.15...done.
Loaded symbols for /usr/lib/libpspell.so.15
Reading symbols from /usr/lib/libgmp.so.3...done.
Loaded symbols for /usr/lib/libgmp.so.3
Reading symbols from /usr/lib/libcurl.so.2...done.
Loaded symbols for /usr/lib/libcurl.so.2
Reading symbols from /usr/lib/libbz2.so.1...done.
Loaded symbols for /usr/lib/libbz2.so.1
Reading symbols from /usr/lib/libaspell.so.15...done.
Loaded symbols for /usr/lib/libaspell.so.15
Reading symbols from /usr/lib/libstdc++.so.5...done.
Loaded symbols for /usr/lib/libstdc++.so.5
Reading symbols from /lib/libgcc_s.so.1...done.
Loaded symbols for /lib/libgcc_s.so.1
Reading symbols from /etc/httpd/modules/mod_python.so...done.
Loaded symbols for /etc/httpd/modules/mod_python.so
Reading symbols from /etc/httpd/modules/mod_ssl.so...Reading symbols from /usr/lib/debug//usr/lib/httpd/modules/mod_ssl.so.debug...done.
done.
Loaded symbols for /etc/httpd/modules/mod_ssl.so
Reading symbols from /usr/lib/libdistcache.so.1...done.
Loaded symbols for /usr/lib/libdistcache.so.1
Reading symbols from /usr/lib/libnal.so.1...done.
Loaded symbols for /usr/lib/libnal.so.1
Reading symbols from /etc/httpd/modules/mod_dav_svn.so...done.
Loaded symbols for /etc/httpd/modules/mod_dav_svn.so
Reading symbols from /usr/lib/libsvn_repos-1.so.0...done.
Loaded symbols for /usr/lib/libsvn_repos-1.so.0
Reading symbols from /usr/lib/libsvn_fs-1.so.0...done.
Loaded symbols for /usr/lib/libsvn_fs-1.so.0
Reading symbols from /usr/lib/libsvn_delta-1.so.0...done.
Loaded symbols for /usr/lib/libsvn_delta-1.so.0
Reading symbols from /usr/lib/libsvn_subr-1.so.0...done.
Loaded symbols for /usr/lib/libsvn_subr-1.so.0
Reading symbols from /etc/httpd/modules/mod_authz_svn.so...done.
Loaded symbols for /etc/httpd/modules/mod_authz_svn.so
Reading symbols from /usr/lib/php/modules/dom.so...Reading symbols from /usr/lib/debug//usr/lib/php/modules/dom.so.debug...done.
done.
Loaded symbols for /usr/lib/php/modules/dom.so
Reading symbols from /usr/lib/php/modules/gd.so...Reading symbols from /usr/lib/debug//usr/lib/php/modules/gd.so.debug...done.
done.
Loaded symbols for /usr/lib/php/modules/gd.so
Reading symbols from /usr/lib/php/modules/imap.so...Reading symbols from /usr/lib/debug//usr/lib/php/modules/imap.so.debug...done.
done.
Loaded symbols for /usr/lib/php/modules/imap.so
Reading symbols from /usr/lib/libc-client.so.0...done.
Loaded symbols for /usr/lib/libc-client.so.0
Reading symbols from /lib/libpam.so.0...done.
Loaded symbols for /lib/libpam.so.0
Reading symbols from /usr/lib/php/modules/ldap.so...Reading symbols from /usr/lib/debug//usr/lib/php/modules/ldap.so.debug...done.
done.
Loaded symbols for /usr/lib/php/modules/ldap.so
Reading symbols from /usr/lib/php/modules/mbstring.so...Reading symbols from /usr/lib/debug//usr/lib/php/modules/mbstring.so.debug...done.
done.
Loaded symbols for /usr/lib/php/modules/mbstring.so
Reading symbols from /usr/lib/php/modules/mysql.so...Reading symbols from /usr/lib/debug//usr/lib/php/modules/mysql.so.debug...done.
done.
Loaded symbols for /usr/lib/php/modules/mysql.so
Reading symbols from /usr/lib/php/modules/ncurses.so...Reading symbols from /usr/lib/debug//usr/lib/php/modules/ncurses.so.debug...done.
done.
Loaded symbols for /usr/lib/php/modules/ncurses.so
Reading symbols from /usr/lib/libpanel.so.5...done.
Loaded symbols for /usr/lib/libpanel.so.5
Reading symbols from /usr/lib/libncurses.so.5...done.
Loaded symbols for /usr/lib/libncurses.so.5
Reading symbols from /usr/lib/php/modules/odbc.so...Reading symbols from /usr/lib/debug//usr/lib/php/modules/odbc.so.debug...done.
done.
Loaded symbols for /usr/lib/php/modules/odbc.so
Reading symbols from /usr/lib/libodbc.so.1...done.
Loaded symbols for /usr/lib/libodbc.so.1
Reading symbols from /usr/lib/libodbcpsql.so.2...done.
Loaded symbols for /usr/lib/libodbcpsql.so.2
Reading symbols from /usr/lib/libltdl.so.3...done.
Loaded symbols for /usr/lib/libltdl.so.3
Reading symbols from /usr/lib/php/modules/pgsql.so...Reading symbols from /usr/lib/debug//usr/lib/php/modules/pgsql.so.debug...done.
done.
Loaded symbols for /usr/lib/php/modules/pgsql.so
Reading symbols from /usr/lib/php/modules/snmp.so...Reading symbols from /usr/lib/debug//usr/lib/php/modules/snmp.so.debug...done.
done.
Loaded symbols for /usr/lib/php/modules/snmp.so
Reading symbols from /usr/lib/libnetsnmp.so.5...done.
Loaded symbols for /usr/lib/libnetsnmp.so.5
Reading symbols from /usr/lib/libelf.so.1...done.
Loaded symbols for /usr/lib/libelf.so.1
Reading symbols from /usr/lib/php/modules/xmlrpc.so...Reading symbols from /usr/lib/debug//usr/lib/php/modules/xmlrpc.so.debug...done.
done.
Loaded symbols for /usr/lib/php/modules/xmlrpc.so
0x00433402 in ?? ()
(gdb) b countm_method_handler
Breakpoint 1 at 0x656f90: file mod_countm.c, line 778.
(gdb) b countm_process_cleanup
Breakpoint 2 at 0x656da1: file mod_countm.c, line 694.
(gdb) c
Continuing.

===================================
At this point, access ex_enter.html
===================================

[Switching to Thread -200692816 (LWP 22804)]

Breakpoint 1, countm_method_handler (r=0x8f453d8) at mod_countm.c:778
778	  countent_t ce=INITIALIZE_COUNTENT;
(gdb) c
Continuing.
[Switching to Thread -169223248 (LWP 22801)]

Breakpoint 1, countm_method_handler (r=0x8fd9e28) at mod_countm.c:778
778	  countent_t ce=INITIALIZE_COUNTENT;
(gdb) c
Continuing.

========================================================
At this point, hit "Submit" button on form ex_enter.html
========================================================

[Switching to Thread -179713104 (LWP 22802)]

Breakpoint 1, countm_method_handler (r=0x8f473e0) at mod_countm.c:778
778	  countent_t ce=INITIALIZE_COUNTENT;
(gdb) c
Continuing.

===================================
At this point, access ex_query.html
===================================

[Switching to Thread -169223248 (LWP 22801)]

Breakpoint 1, countm_method_handler (r=0x8fdfe40) at mod_countm.c:778
778	  countent_t ce=INITIALIZE_COUNTENT;
(gdb) c
Continuing.

===============================================================
At this point, access any webpage, like http://localhost/manual
===============================================================

Program received signal SIGHUP, Hangup.
[Switching to Thread -211182672 (LWP 22805)]
0x00433402 in ?? ()
(gdb) c
Continuing.

Program received signal SIGTERM, Terminated.
[Switching to Thread -150441856 (LWP 22799)]
0x00433402 in ?? ()
(gdb) c
Continuing.
[Thread -200692816 (zombie) exited]
[Thread -211182672 (zombie) exited]
[Thread -179713104 (zombie) exited]
[Thread -169223248 (zombie) exited]
[Thread -190202960 (zombie) exited]

Breakpoint 2, countm_process_cleanup (p=0x8ed6900, bSS=0) at mod_countm.c:694
694	  int i=0;
(gdb) b 733
Breakpoint 3 at 0x656e94: file mod_countm.c, line 733.
(gdb) c
Continuing.

Breakpoint 3, countm_process_cleanup (p=0x8ed6900, bSS=0) at mod_countm.c:733
733	  for (i=0; i<COUNTM_BDB_MAX_DB; ++i) {
(gdb) c
Continuing.

Program exited normally.
(gdb) q
[root@waiter mod_countm-5.3]# /etc/rc.d/init.d/httpd stop
Stopping httpd:                     [OK]
[root@waiter mod_countm-5.3]#

8.6  Debugging FreeBSD 5.4-RELEASE

The apache-2.0.50_3 package must be rebuilt using make -DWITH_DEBUG for the debugging scripts to work properly.
First, install apache-2.0.53_3 package, then delete it. Rebuild the port, then make a new package, and install that. As an extra precaution, you may want to adjust PORTVERSIONS.

Chapter 9
Additional Information

9.1  mod_ometer

If the directive CountmDBPriority is set OFF, then some compatibility with mod_ometer is maintained. Once the counter is entered into the database, the idea is to be URL compatible with ometer. The compile time option MODULE_URI_PATH_STRING should be changed and the config file <Location> directive must set to the same value.

9.2  Network sniffers

Network traffic sniffers may seek to identify sites running mod_countm. Although the module was written within the Apache API, vulnerabilities probably exist. A easy method to disguise your counter installation is to alter MODULE_URI_PATH_STRING to a new value, and adjust <Location> to that new value. Rebuild mod_countm, and restart the server. The new URIs will now use:
http://localhost/newvalue&link=

to access the counter, and
http://localhost/newvalue/fonts

to list available fonts.
Althouth link is common, network sniffers will still be able to identify the link= portion. The compile time option COUNTM_PARAMETER_LINK may be used to change the link= value. Then, a typical counter query (CountmDBPriority ON) would be written as:
http://localhost/newvalue?newlink=




File translated from TEX by TTH, version 3.40.
On 7 Jan 2006, 15:48.