Tuesday, February 12, 2008

Simple .net BST

using System;
using System.Collections.Generic;
using System.Text;

namespace BinarySearchTree
{
internal class Node where T: IComparable
{
private T _data;
private Node leftNode = null;
private Node rightNode = null;

internal Node(T data)
{
_data = data;
}

internal Node LeftNode
{
get
{
return leftNode;
}
set
{
leftNode = value;
}
}

internal Node RightNode
{
get
{
return rightNode;
}
set
{
rightNode = value;
}
}

internal int CompareTo(T val)
{
return _data.CompareTo(val);
}
}
}


----------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Text;

namespace BinarySearchTree
{
public class BinarySearchTree where T : IComparable
{
private Node rootNode = null;

public BinarySearchTree()
{
}

public void Insert(T val)
{
rootNode = Insert(rootNode, val);
}


private Node Insert(Node node, T val)
{
if (node == null)
{
node = new Node(val);
return node;
}

if (node.CompareTo(val) >= 0)
{
node.LeftNode = Insert(node.LeftNode, val);
}
else
{
node.RightNode = Insert(node.RightNode, val);
}

return node;
}
}
}

----------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Text;

namespace BinarySearchTree
{
class Program
{
static void Main(string[] args)
{
BinarySearchTree bns = new BinarySearchTree();

bns.Insert(3);
bns.Insert(2);
bns.Insert(10);
bns.Insert(1);
bns.Insert(4);
bns.Insert(11);
}
}
}

Tuesday, February 5, 2008

Simple Pointers

int cmp(const int i, const int j)
{
if (i == j)
{
return 1;
}

return 0;
}

void search(const int val, const int *p, int (*compare)(const int i, const int j))
{
int ret = 0;
for (int i = 0; i < 10; i++)
{
ret = compare(val, p[i]);
if (ret == 1)
{
printf("value found");
return;
}
}

printf("value not found");
}

int _tmain(int argc, _TCHAR* argv[])
{
int num[] = {100, 1,2,3,4,15,6,7,8,9,10};
int *p = num;
int **pp = &p;

printf("*p = %d\n", *p);
printf("p[0] = %d\n", p[0]);
printf("p[1] = %d\n", p[1]);
printf("*p++ = %d\n", *p++);
printf("*p = %d\n", *p);
printf("*p-- = %d\n", *p--);
printf("*p = %d\n", *p);
printf("*++p = %d\n", *++p);
printf("*--p = %d\n", *--p);
printf("*(p++) = %d\n", *(p++));
printf("*p = %d\n", *p--);
printf("*p+5 = %d\n", *p+5);
printf("*(p+5) = %d\n", *(p+5));

printf("**pp = %d\n", **pp);

search(2, num, cmp);


getc(stdin);
return 0;
}


OUTPUT:
*p = 100
p[0] = 100
p[1] = 1
*p++ = 100
*p = 1
*p-- = 1
*p = 100
*++p = 1
*--p = 100
*(p++) = 100
*p = 1
*p+5 = 105
*(p+5) = 15
**pp = 100
value found

Windows Threading

include windows.h
HANDLE CreateThread(LPSECURITY_ATTRIBUTES secAttr,
SIZE_T stackSize,
LPTHREAD_START_ROUTINE threadFunc,
LPVOID param,
DWORD flags,
LPDWORD threadID);

Thread can be destroyed by calling CloseHandle(HANDLE );
or BOOL TerminateThread(HANDLE thread, DWORD status); //no cleanup
VOID ExitThread(DWORD status); //cleanup stacks

The Visual C++ alternatives to CreateThread( ) and ExitThread( ) are _beginthreadex( ) and _endthreadex( ). Both require the header file .

DWORD SuspendThread(HANDLE hThread);
DWORD ResumeThread(HANDLE hThread);
DWORD GetPriorityClass(HANDLE hApp);
BOOL SetPriorityClass(HANDLE hApp, DWORD priority);
HANDLE GetCurrentThread(void); //get the main thread

Windows Synchronization:
- Semaphore
- Mutex //global object can be used by multi process
- Event Object
- Waitable Timer
- Critical section

MUTEX:
HANDLE CreateMutex(LPSECURITY_ATTRIBUTES secAttr, BOOL acquire, LPCSTR name);
name = NULL => localized sync
A mutex handle is automatically closed when the main process ends. You can explicitly close a mutex handle when it is no longer needed by calling CloseHandle( ).
DWORD WaitForSingleObject(HANDLE hObject, DWORD howLong);
BOOL ReleaseMutex(HANDLE hMutex);

if(WaitForSingleObject(hMutex, 10000)==WAIT_TIMEOUT) {
// handle time-out error
}

// access the resource

ReleaseMutex(hMutex);















Friday, January 25, 2008

ASP .Net Ajax for VS 2005

This section discuss the basic steps to add ajax to your existing asp .net page for VS 2005. Three basic steps to follow:

- Download and install ASP .net AJAX extension
go to http://www.asp.net/ajax/downloads/

- In the toolbox of VS2005 you should have the AJAX Extensions added.
What's important to note is the ScriptManager, and UpdatePanel. The rest is more advance topics you can find reference from http://www.asp.net/ajax

- So let's see how to simple ajax behavior to an existing web asp .net page.
1. Copy the web.config from the ajax download to your own web.config
2. Add Scriptmanager to the page
3. Add the UpdatePanel to the page section you want postback with the
ContentTemplate section.

That's all to do to add ajax capbility to section of your page. Note that the page lifecycle is still called, but during the page rendering phase only the required updatepanel section is transfered.

Wednesday, October 24, 2007

Trace system calls

A nice way to trace a system call is to use the strace command.

ex: strace ls

And: strace -c ls
to get some statistics. Really nice debugging tool for filesystem writer.

Monday, October 22, 2007

Kenel Debugging Techniques

This is an important topic to discuss the issue of debugging with Linux Kernel. What is the best way to debug the kernel? When facing with a race condition, crash, or freeze that we have no control of? In this topic I'll try to explore the various ways of debugging the kernel. Let me first list all the existing techniques and go through the details of each (let me know if there's other I'm not aware of). Followed by an explanation of which one I consider the best for debugging (personal view).

- Logging or debug trace through kdprint messages (/var/log/messages) dmesg
- Step through the kernel code using gdb debugger
- Using a serial port to debug from another machine
- Reading the kernel source code
- Sending system interrupt control when frozen
- Analyze oops message, dump object file

My point of view for the best way of debugging a kernel is put trace logs. The trace allows you to know the last point where the crash occurs:

You can use dmesg to print the kernel ring buffer or simply tail the /var/log/messages that's where most kernel kdprint message goes. Similar to printf, kdprint prints out the kernel message. This technique helps during debug mode as you don't want to print traces all around.

Using gdb is harder for kernel debugging, anyone tried? You also need to build a debug version of the kernel if I'm not mistaken.

Using a serial port I never tried that but worth trying.

Sometimes you may get a BUG from the kernel source, due to your code passing some wrong values. It's like an ASSERT from the kernel. This is easy to solve as you can directly read the source code where the BUG occurs. In many cases it may be dangerous reading the kernel source as some may be too tempted to patch it so it won't BUG anymore. My point of view the kernel source is for you to understand the behavior and not to patch. Until you understand it don't patch anything...

Another way of debugging is to analyze a oops message. Linux generates oops message caused by segmentation fault, etc... You can also try to generate an oops message when the machine does not respond anymore, in that case the kernel may be in deadlock scenario. You can configure the kernel to respond to some interrupt keys like ctrl-sysrq.

What is an oops message. oops message is similar to kernel dump file in Windows not as much information though, but basically you may find your last EIP address to trace back the last call before the crash.

If your oops message is not detailed enough, you can use the ksymoops command on linux to generate more detailed information. With an oops file, one can also dump the object file to figure out the last access line of code before the crash. A nice command in linux is the objdump command.

That's enough for today, more on this later......

File explained...

A file object is used for reading or writing the data. A set of operations is defined to allow read/write from/to the data. The file structure keeps a pointer to the dentry of the opened file which holds a reference to the inode. Files are accessible to processes through their file descriptors. The process id is maintained inside the file owner field with a signal to deliver data to the process. A file can be memory mapped directly using mmap.


struct file_operations {
loff_t (*llseek) (struct file *, loff_t, int);
ssize_t (*read) (struct file *, char *, size_t, loff_t *);
ssize_t (*write) (struct file *, const char *, size_t, loff_t *);
int (*readdir) (struct file *, void *, filldir_t);
unsigned int (*poll) (struct file *, struct poll_table_struct *);
int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
int (*mmap) (struct file *, struct vm_area_struct *);
int (*open) (struct inode *, struct file *);
int (*flush) (struct file *);
int (*release) (struct inode *, struct file *);
int (*fsync) (struct file *, struct dentry *);
int (*fasync) (int, struct file *, int);
int (*check_media_change) (kdev_t dev);
int (*revalidate) (kdev_t dev);
int (*lock) (struct file *, int, struct file_lock *);
};