PHP 5.2 on CentOS

PHP 5.2 brings lots of little useful features and CentOS 5.3 comes with PHP 5.1. So most of my PHP apps failed. The easiest way to solve this is to :

  • Edit /etc/yum.repos.d/CentOS-Testing prix viagra viagra.repo and put this :
    1
    2
    3
    4
    5
    6
    
    [c5-testing]
    name=CentOS-5 Testing
    baseurl=http://dev.centos.org/centos/5/testing/$basearch/
    enabled=1
    gpgcheck=1
    gpgkey=http://dev.centos.org/centos/RPM-GPG-KEY-CentOS-testing
  • Launch :
    1
    
    yum update php

Source :
http://www.freshblurbs.com/install-php-5-2-centos-5-2-using-yum

get start-stop-daemon on any Linux distribution

I switched from Debian to CentOS because I had the choice between an old 32 bits Debian 4.0 or a brand new 64 bits CentOS 5.3. And I have some scripts that use the great “start-stop-daemon” tool, which isn’t available on CentOS.

The easiest way to solve this problem is to get dpkg from Debian and then try to compile it. It’s likely that it will fail because libselinux (and it’s subsidiary library libsepol) won’t be registered in the pkgconfig dir. But we don’t really care as we only need start-stop-daemon, not dpkg.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# wget http://ftp.de.debian.org/debian/pool/main/d/dpkg/dpkg_1.14.25.tar.gz
# tar -xf dpkg_1.14.25.tar.gz
# cd dpkg-1.14.25/
# ./configure >/dev/null
configure: WARNING: x86_64 not found in cputable
configure: WARNING: linux-gnu not found in ostable
Package libselinux was not found in the pkg-config search path.
Perhaps you should add the directory containing `libselinux.pc'
to the PKG_CONFIG_PATH environment variable
No package 'libselinux' found
configure: WARNING: no curses library found
# make >/dev/null
processarc.o: In function `process_archive':
/root/dpkg-1.14.25/src/processarc.c:166: warning: the use of `tmpnam' is dangerous, better use `mkstemp'
archives.o: In function `tarobject':
/root/dpkg-1.14.25/src/archives.c:634: undefined reference to `matchpathcon'
/root/dpkg-1.14.25/src/archives.c:640: undefined reference to `setfscreatecon'
/root/dpkg-1.14.25/src/archives.c:802: undefined reference to `setfscreatecon'
/root/dpkg-1.14.25/src/archives.c:804: undefined reference to `freecon'
/root/dpkg-1.14.25/src/archives.c:826: undefined reference to `setfscreatecon'
/root/dpkg-1.14.25/src/archives.c:618: undefined reference to `is_selinux_enabled'
collect2: ld returned 1 exit status
make[2]: *** [dpkg] Error 1
make[1]: *** [all-recursive] Error 1
make: *** [all] Error 2
# cd utils
# make install
gcc -std=gnu99 -DHAVE_CONFIG_H -I. -I.. -DLOCALEDIR=\"/usr/local/share/locale\" -idirafter ../libcompat -I../lib    -g -O2 -MT start-stop-daemon.o -MD -MP -MF .deps/start-stop-daemon.Tpo -c -o start-stop-daemon.o start-stop-daemon.c
mv -f .deps/start-stop-daemon.Tpo .deps/start-stop-daemon.Po
gcc -std=gnu99  -g -O2  -Wl,-O1 -o start-stop-daemon start-stop-daemon.o ../libcompat/libcompat.a
make[1]: Entering directory `/root/dpkg-1.14.25/utils'
test -z "/usr/local/sbin" || /bin/mkdir -p "/usr/local/sbin"
  /usr/bin/install -c 'start-stop-daemon' '/usr/local/sbin/start-stop-daemon'
make[1]: Nothing to be done for `install-data-am'.
make[1]: Leaving directory `/root/dpkg-1.14.25/utils'

Even if it doesn’t look so good, it should have installed the start-stop-daemon software.

Server moved

I’ve switched from my two three years old dedicated servers to one brand new virtual server. Reasons are : These servers costed me too much and they were becoming old (risk of failure increases). It wasn’t worth it.

I spent last night doing that because I didn’t want to interrupt anybody using these servers.

My two servers were running some Debian and I’m now switching to a CentOS virtual server. I was a little bit worried at first that CentOS would have a crappy package management system, but its yum is in fact working the same way as Debian’s apt-get and OpenSuse’s zypper. The oool thing is that these three package management systems roughly work the same way : install , you don’t have to learn a new “ultimate” way to upgrade your software (like on FreeBSD). By the way, the faster package management system is yum, and the slowest one is zypper.

The biggest problem I had so far was to move all the databases. Previously, I was always using some Debian hosts, I was using exactly the same version of MySQL, so I just had to copy the MySQL datadir and logs files. Here, I had to export/import everything.

CentOS has an antique 1.2.4 version of Mono (when the current version is 2.4). I couldn’t manage to compile from the tarball but compiling from the SVN worked fine.

1
2
3
4
5
6
7
8
9
]# /usr/local/bin/mono --version
Mono JIT compiler version 2.5 (/trunk/mono r140917 Sat Aug 29 05:29:19 CEST 2009)
Copyright (C) 2002-2008 Novell, Inc and Contributors. www.mono-project.com
        TLS:           __thread
        GC:            Included Boehm (with typed GC and Parallel Mark)
        SIGSEGV:       altstack
        Notifications: epoll
        Architecture:  amd64
        Disabled:      none

Microchip Zena Analyser – Zena .zna file format

I recently thought that it could be interesting to automatically get everything I needed about a MiWi network using a program reading the .zna capture files. I wanted to check every data sent on the 802.15.4 layer at a higher layer than Zena.

But the project has been cancelled, so I won’t make this program. But still, I decided to give the format of the file for those who would have the same needs.

everything is Little Endian

1
2
3
4
5
6
7
[ 4 ] - Frame Number (starting at 0) : 00 00 00 00 is frame 1, 01 00 00 00 is frame 2
[ 4 ] - Time 
[ 1 ] - Length of the frame (remember it counts the 2 last mandatory bytes) 
[ 2 ] - Mac Frame Control
[ 0-125 ] - Frame content
[ 1 ] - RSSI
[ 1 ] - Corr + CRC

MSB of this last byte describes if the CRC is OK.

In .Net, making this program is pretty easy. You just have to read the first 9 bytes. You will then read the next X (given by the 9th byte) + 3 bytes. Converting these bytes into a readeable message is easy :

1
2
3
4
5
6
7
8
9
10
var frameHeader = new Byte[] { 
    0, 0, 0, 0, 
    0, 0, 0, 0,
    4
};
var rawFrameNumber = new Byte[4];
Array.Copy(frameHeader, 0, rawFrameNumber, 0, rawFrameNumber.Length); 
if (!BitConverter.IsLittleEndian) // .Net isn't x86 specific
    Array.Reverse(rawFrameNumber, 0, rawFrameNumber.Length);
var frameNumber = BitConverter.ToUInt32(rawFrameNumber, 0);

Microsoft Office 2010 (Tech Preview)

I’m in holiday right now. I received invitation from Microsoft to test their Office 2010. I’ve downloaded it (with my HSPDA card which is very slow (5 to 40 KB/s) here). It looks like they took the time to improve everything in order to reach the level of Word/Excel/Powerpoint 2007. These 3 products haven’t changed much, they just have some new colors, a new special menu and some new little features.

I know that they have made some other great improvements everywhere, but what I can see is :
– Each office app loads in a very short time.
– Each office app has a new Office button from which one you can do lot of advanced things, on your current document or your current application. It’s called the backstage view and it’s very pretty.
– Outlook has been significantly improved, it doesn’t seem to get every pixel of each mail from your hardrive anymore.
… well, in fact I spend much more time on Visual Studio than I do on the Office suite applications …

You should just take care about something : If you have Office 2007 (which is only available in 32 bits) and you download Office 2010 64 bits version like I did, you will have to uninstall Office 2007.

I’m really glad I had the chance to download this software legally. Now, dear Microsoft, if you could send me a tech preview of Sharepoint 2010 I would be super happy. This is quite disturbing because you gave me access to Sharepoint Designer 2010, but that’s the software I hate in the (rare) Microsoft SharePoint 2007 tools.

Here is the email invitation I received :

Inside Sharepoint

I recently took the time to take a look inside the Microsoft.Sharepoint.dll using reflector. I’m not sure I have the right to do that. And I’m pretty sure I don’t have the right to publish any code extracted from it, so I won’t show any.

Using SPSite(s) and SPWeb(s)
If you do some timing on the SPWeb creation call (SPSite.OpenWeb), you will find out that it’s freaking fast (less then 1 ms on my server). The reason is that the most heavy object, the SPRequest class, is shared among SPWebs of a SPSite. The Dispose call only “Invalidate” the SPWeb, and if this SPWeb is the owner of the SPRequest (which is SPContext.Current.Web object in most of the cases), it releases it.

Personnaly, I like to have something like that when I use a particular SPWeb along my code in a WebPart :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
private SPWeb _rootWeb;
public SPWeb RootWeb {
    get {
        if ( _rootWeb == null ) {
            _rootWeb = SPContext.Current.Site.RootWeb;
            if ( _rootWeb != SPContext.Current.Web )
                _toDispose.Add( _rootWeb );  
        }
        return _rootWeb;
    }
}
 
private List<IDisposable> _toDispose = new List<IDisposable>();
protected override void OnUnLoad() {
    foreach( var disp in _toDispose )
        disp.Dispose();
}

But the code above won’t make you gain a 1 ms compared to this code (which is shorter and potentially safer, you don’t need to dispose everything) :

1
2
3
4
5
6
7
8
var rootWeb = SPContext.Current.Site;
try {
    // Your code
}
finally {
     if ( rootWeb != SPContext.Current.Web )
         rootWeb.Dispose();
}

If you had to access some more indirect objects, you certainly should keep the code showed earlier. For instance to use a SuperToken Web :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
private SPSite _stSite;
SPSite STSite {
    get {
        if ( _stSite == null ) {
            _stSite = new SPSite( SPContext.Current.Site.Url, SPContext.Current.Site.SystemAccount.UserToken );
            if ( _stSite != SPContext.Current.Site )
                _toDispose.Add( _stSite );
        }
        return _stSite;
    }
}
 
private SPWeb _stWeb;
SPWeb STWeb {
    get {
        if ( _stWeb == null ) {
            _stWeb = STSite.OpenWeb( SPContext.Current.Web.Url );
            if ( _stWeb != SPContext.Current.Web )
                _toDispose.Add( _stWeb );
        }
        return _stWeb;
    }
}
 
private List<IDisposable> _toDispose = new List<IDisposable>();
protected override void OnUnLoad() {
    foreach( var disp in _toDispose )
        disp.Dispose();
}

Here, opening these new SPSite and SPWeb takes 200 ms on my server. Making sure this only happen once per webpart (or better, per page) can really boost your performances.

The SPRequest object
Well… I was very disapointed, the SPRequest object references an SPRequestInternalClass from the Microsoft.Sharepoint.Library assembly which only uses interrop COM+ methods. So, it’s basically wrapping COM+ methods. The SPRequest does a lot of exception handling and it keeps track of where (with the stacktrace) it has been created and the size of the “unmanaged stack”.

Optimization
I like how they did their code. It’s pretty optimized (they even use a bunch of gotos). But sometimes there is some weird things and I don’t know if it’s the compiler’s or the developer’s fault. If you look at the code, they have an SPRequestManager.SPRequestsPerThreadWarning property, which gets (in the Registry, at “HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Shared Tools\Web Server Extensions\HeapSettings\LocalSPRequestWarnCount”) the max number of opened SPRequest objects opened before logging it (or 8 if this entry doesn’t exist), that takes twice the amount of code it would normaly require.

The limit of disassembling
The most frustrating part is there are tons of really important methods that are obfuscated (and that .Net reflector doesn’t disassemble, it could at least give the IL code in comments). I just have :

1
2
3
private static void xxx() {
    // This item is obfuscated and can not be translated.
}

For instance, I really would have liked to see how works the SPList.Update() method, but it’s also obfuscated.

You should explore it too
In the Microsoft.Office.Server.Search assembly, you will also find some pretty interesting things. If you look how works the standard search webparts, well you will be pretty disapointed. The advanced search uses an internal (in the C# meaning) shared object.

Before doing your own webpart, you should take a look at the overriden methods of some sharepoint webparts. It can show you, for instance, how to create your own toolparts. In my last project, I used a stupid text property instead of using a DropDownList in a ToolPart, I was very disappointed with myself when I discovered this.