About
RSS

Sqlite pitfall


i wanted to store a set of prime numbers together with other data. So i turned to my database of choice, sqlite3. Since sqlite has a tendency to automatically convert stuff into other stuff (flexible typing), i set the type for the prime explicitly to TEXT, because (quoted from flexible typing)

Note that an INTEGER or REAL value will never end up being stored in a TEXT column, since an INTEGER or REAL value can and always will be converted into its equivalent TEXT representation.

So:
CREATE TABLE IF NOT EXISTS
primes (
    id INTEGER PRIMARY KEY,
	prime TEXT UNIQUE ON CONFLICT IGNORE,
	T INTEGER,
	k FLOAT);

INSERT INTO PRIMES (prime, T, k) VALUES (
736967235538117954978726019337077632830443,
1234,
0.5);

SELECT * FROM primes;
But this unexpectedly returns
1|7.36967235538118e+41|1234|0.5

So the INSERT silently (and contrarily to the documentation) converts the prime into a boring, inexact float.

The fault lies partly with me, since it should have been

INSERT INTO PRIMES (prime, T, k) VALUES (
'736967235538117954978726019337077632830443',
1234,
0.5);

(notice the quotes around the prime). But i would have expected an error when inserting an unquoted series of digits into a TEXT column.

It is possible (but not well documented ) to have sqlite3 throw errors in this case, by adding a (non-SQL-standard) STRICT at the end of the CREATE TABLE statement (as in “I put types on this table, and this time I really mean it”).

Tue, 04 Nov 2025
[/osfail] permanent link

Programming Pearls: malloc, the Zabbix way


The Zabbix sources define zbx_malloc in include/common.h: line 700 as:


#define zbx_malloc(old, size)   zbx_malloc2(__FILE__, __LINE__, old, size)

zbx_malloc2 is defined in src/libs/zbxcommon/misc.c: line 255 as:


void    *zbx_malloc2(const char *filename, int line, void *old, size_t size)
{
    int max_attempts;
    void    *ptr = NULL;

    /* old pointer must be NULL */
    if (NULL != old)
    {
        zabbix_log(LOG_LEVEL_CRIT, "[file:%s,line:%d] zbx_malloc: " 	
				"allocating already allocated memory. "
                "Please report this to Zabbix developers.",
                filename, line);
        /* exit if defined DEBUG, ignore otherwise */
        zbx_dbg_assert(0);
    }

    for (
        max_attempts = 10, size = MAX(size, 1);
        0 < max_attempts && NULL == ptr;
        ptr = malloc(size), max_attempts--
    );

    if (NULL != ptr)
        return ptr;

    zabbix_log(LOG_LEVEL_CRIT, "[file:%s,line:%d] zbx_malloc: out of memory."
		"Requested " ZBX_FS_SIZE_T " bytes.",
            filename, line, (zbx_fs_size_t)size);

    exit(FAIL);
}

So where're the pearls in this?

  1. the old parameter is forced to be NULL, so why pass it at all???

  2. noticed the for loop? It tries to malloc ten times before giving up. This seems to assume that some concurrently running part of zabbix frees memory, or that the system suddenly (while this loop is running, that is) assigns a higher memory bound for zabbix.

  3. noticed the MAX in the for loop? It tries to catch and disguise the error of requesting zero bytes by always returning at least one byte

Fri, 05 Apr 2013
[/osfail] permanent link

MySQL cannot erase data


For eight years it has been known (and Verified) that MySQL does not release diskspace it has claimed in its ibdatax files. The bug leads to full disks and database outages since the only way arround it is to shut down the DB, dump it (consuming even more space) scrubbing the disk and restoring from dump.

This is a veritable showstopper.

Fri, 13 Jan 2012
[/osfail] permanent link

OpenLDAP WTF


Since NIS has seen its hayday (in the early 90ies), we switched to the highly secure LDAP+Kerberos setup. OpenLDAP is touted as the allround “Solution” to all user account management, sorry, I meant to say account provisioning. After converting our NIS passwd file to thousands of LDIF files we imported them with the obvious three-liner

 
  for i in *ldif; do \
	ldapadd -v -W -D "cn=admin,dc=our,dc=domain" \
	    -c -H ldapi:/// -f $i
  done
 
 

After fiddling with half a dozen files in /etc, the client systems could look up user data on the LDAP server. Our test for that was

 
  getent passwd aknownuser
  getent passwd anotherknownuser
 
 
So it seemed plausible to create a list of all users by
	
  getent passwd | awk -F: '{print $1}' > allourusers
	
and install that as a list of valid recipients of e-mails.

This was a grave error, because one of the manymany default settings of OpenLDAP is to return only the first 500 answers to any request. So the list was short by a few hundred accounts.

Considering that LDAP has no concept of a cursor and one cannot ask for the next 500  entries, one can only ask

What the fsck were they thinking???

Mon, 28 Nov 2011
[/osfail] permanent link

Including by explicitly excluding files in Bacula


Bacula's config file format allows the following


FileSet {
	Name = Blah 
	Exclude {
		Options {
			wilddir = /var/tmp*
		}
	}
	File = /var
}

The Directory /var/tmp from the Exclude section is included in the backup, because to exclude it, the proper config would be


FileSet {
	Name = Blah 
	Exclude {
		Options {
			wilddir = /var/tmp*
		}
		exclude = yes
	}
	File = /var
}

Tue, 25 Jan 2011
[/osfail] permanent link