This can be done, although there is no automatic mechanism to do this.
Basically you have to check out using --depth=immediates so the contents of the folders are not checked out. After that, you need to run svn update --set-depth=infinity for all the folders in which you need the files to be checked out.
Programming Hints
28 August 2014
11 March 2014
Adding format specifiers to printf
It is possible to add specifiers for the printf function family. To do this, the register_printf_specifier can be used.
Two functions must be created for this.
Afterwards, at the start of the program, the register_format_specifier must be called with the two functions and the specifier as parameters.
This should print the data variable as specified in the print_data_structure_to_string function. However, while the program will compile, there are two major issues with it.
Firstly, the register_format_specifier function is a GNU extension, it is not part of the ISO C standard.
Secondly, while the program will compile and execute correctly, the compiler (gcc) will give warnings when compiling with -Wformat (or -Wall), and these warnings cannot be avoided, since it is not possible to add specifiers to the ones supported by the gcc static check.
Two functions must be created for this.
int print_data_struture(FILE *stream, const struct printf_info *info, const void *const *args)
{
char buffer[256];
int len = 0;
data_structure_t *data = 0;
data = *((data_structure_t **)(args[0]));
print_data_structure_to_string(buffer, data);
len = fprintf(stream, "%*s", (info->left?-info->width:info->width), buffer);
return len;
}
int print_data_structure_arginfo(FILE *stream, const struct printf_info *info, const void *const *args)
{
if (n>0) {
argtypes[0] = PA_POINTER;
return 1;
}
return 0;
}
Afterwards, at the start of the program, the register_format_specifier must be called with the two functions and the specifier as parameters.
int main()
{
register_print_specifier('W', print_data_structure, print_data_structure_arginfo);
...
data_structure_t data;
/* initialize data */
...
printf("%W\n", &data);
This should print the data variable as specified in the print_data_structure_to_string function. However, while the program will compile, there are two major issues with it.
Firstly, the register_format_specifier function is a GNU extension, it is not part of the ISO C standard.
Secondly, while the program will compile and execute correctly, the compiler (gcc) will give warnings when compiling with -Wformat (or -Wall), and these warnings cannot be avoided, since it is not possible to add specifiers to the ones supported by the gcc static check.
07 March 2014
Wireshark over SSH ... over SSH
Running Wireshark on a remote machine using SSH is not a very complex task, and there are many solutions for this on the web. However, the task becomes slightly more complex when you have to access a remote machine through another remote machine (e.g. you SSH to machine A and from there SSH to machine B).
This is the solution I found, using FIFO pipes.
On the remote machine where you have to listen, you create a FIFO pipe. You do the same thing on the intermediary machine.
After that, you read the pipe from the intermediary machine on the local host and pipe it to wireshark.
On the intermediary machine, you pipe the output of the machine you are listening for packets on to the local pipe.
The last step is to start tcpdump on the remote host and pipe the result to the FIFO pipe.
Wireshark should now be showing the packets captured by tcpdump.
This is the solution I found, using FIFO pipes.
On the remote machine where you have to listen, you create a FIFO pipe. You do the same thing on the intermediary machine.
mkfifo /tmp/wirefifo
ssh user@hostA "cat /tmp/wirefifo" | wireshark -k -i -
ssh user@hostB "cat /tmp/wirefifo" > /tmp/wirefifo
tcpdump -s 0 -U -n -w - -i any not port 22 > /tmp/wirefifo
19 September 2012
Colors in Makefile
If echo doesn't take escape sequences into consideration, simply run the command with the -e parameter (Small e, not capital E, since capital E disables escape sequence parsing).
VMWare in Fedora 17
I recently had to create a Virtual Machine with Fedora 17. I had to manually install the VMWare Tools, so I ran the script, and I got an error regarding the kernel headers.
The solution to that was upgrading the kernel to the same version as the kernel headers I had. I found it in this thread.
http://forums.fedoraforum.org/showthread.php?t=263717
Now I don't know if the reboot is necessary, and installing the kernel-devel just told me that it is already up to date, so I'm not sure that's necessary either.
Anyway, it works, so all is good.
Also, GCC may be missing. Since I use that nayway, I usually just go for installing the whole Development Tools package group.
The solution to that was upgrading the kernel to the same version as the kernel headers I had. I found it in this thread.
http://forums.fedoraforum.org/showthread.php?t=263717
yum update kernel
reboot
yum install kernel-devel
Also, GCC may be missing. Since I use that nayway, I usually just go for installing the whole Development Tools package group.
yum groupinstall "Development Tools"
29 February 2012
Hash tables with 2 keys
Let's say you have a structure, which has an identifier (a string), an index (a number), and various data. I tried to find a good solution to create a hash table in which I would be able to search for an element after its identifier or its number. This is what I came up with:
So obviously, when we're adding the element to the table, we calculate the hash value of the identifier.
Next, we generate the index based on the hash value. We simply keep an incremented value in each hash table slot, multiply it by the hash table size and add the hash value, and then simply add the structure to the list.
Now, when we want to search for an element in the hash table we do the following:
In order to look after an identifier:
In order to look after an index we simply do a modulo operation. The value resulted is exactly the hash value that was generated when the element was added to the list, and will be the same as the hash value calculated by the function if applied to the identifier of the element.
typedef struct {
char* identifier;
int index;
void* data;
} my_type_t;
int hash = hash_function(my_struct->identifier);
my_struct->index = (hash_table[hash]->add_structure_to_list(my_struct, hash_table[hash]);
hash_table[hash]->current_index += 1;
In order to look after an identifier:
int hash = hash_function(identifier);
for (element=hash_table[hash]->head;element;element=element->next) {
if (!strcmp(element->identifier, identifier)) {
return element;
}
}
int hash = index % hash_size;
for (element=hash_table[hash]->head;element;element=element->next) {
if (element->index == index) return element;
}
06 February 2012
Read-Write Locks
Using locks inevitably serializes a multiprocessed/multithreaded application. Now this would not be a problem if the locks are gotten for very short periods of time. However, if not, the whole advantage of parallel processing is lost.
A solution for that are read-write locks. Data can be read by multiple threads/processes in parallel, so as long as no process/thread modifies the data, it would be ok. For this situation, read-write locks can be used.
The way these work is as follows:
Read-Write locks actually contain 2 locks, a read lock and a write lock. The write lock is set when a process/thread is writing, while the read lock is incremented when a process/thread is reading, and decremented when done.
To avoid reading while the data is being written, a reader gets the write lock. Once the lock is gotten, the read lock is incremented and the write lock is released again. This way, the write lock is only set for a very short time amount of time.
To avoid writing while the data is being read, a writer first gets the write lock. This will prevent any new reader to continue reading the data. The writer then waits until the reader lock decrements to 0, meaning that all readers who had the lock before the write lock was gotten, finish reading. After this, the data is modified, and then the write lock is released again, allowing the readers who were waiting for the write lock to continue their processing.
Here's the code for it (I won't add the implementation for the get_lock and release_lock function, to save space, and because I am lazy to write it here).
The Lock structure is easy, it basically looks like this:
Function for getting the read lock. The function increases the read lock, with the write lock gotten.
Function for releasing the read lock. The function just decrements the read lock.
Function for getting the write lock. The function also waits for all the readers to finish. The get_lock_no_set function is almost the same as get_lock function, the difference being that this one doesn't modify the lock, it just waits for the lock to be 0 and then returns.
Function for releasing the write lock.
Here's what would happen if you use this kind of locks. The writer has to have both locks when it writes, and while it does, both readers have to wait for it to finish before reading. The timeline shows an application with 3 reader threads and one writer (I know, the 'drawing' is bad, but meh, it's what I could come up with at one in the morning ....)
The way these work is as follows:
Read-Write locks actually contain 2 locks, a read lock and a write lock. The write lock is set when a process/thread is writing, while the read lock is incremented when a process/thread is reading, and decremented when done.
To avoid reading while the data is being written, a reader gets the write lock. Once the lock is gotten, the read lock is incremented and the write lock is released again. This way, the write lock is only set for a very short time amount of time.
To avoid writing while the data is being read, a writer first gets the write lock. This will prevent any new reader to continue reading the data. The writer then waits until the reader lock decrements to 0, meaning that all readers who had the lock before the write lock was gotten, finish reading. After this, the data is modified, and then the write lock is released again, allowing the readers who were waiting for the write lock to continue their processing.
Here's the code for it (I won't add the implementation for the get_lock and release_lock function, to save space, and because I am lazy to write it here).
The Lock structure is easy, it basically looks like this:
typedef struct {
volatile int read;
volatile int write;
} rwlock_t;
void rwlock_get_rd(rwlock_t *lock)
{
get_lock(&(lock->wr));
lock->rd += 1;
release_lock(&(lock->wr));
}
void rwlock_release_rd(rwlock_t *lock)
{
lock->rd -= 1;
}
void rwlock_get_wr(rwlock_t *lock)
{
get_lock(&(lock->wr));
get_lock_no_set(&(lock->rd));
}
void rwlock_release_wr(rwlock_t *lock)
{
release_lock(&(lock->wr));
}
______________________________________________________________________________ Reader 1 | RD | -========= -========== -=========== | WR | -= -= -------------= ______________________________________________________________________________ Reader 2 | RD | -========= -=========== -=========== | WR | --= -= ------------= ______________________________________________________________________________ Reader 3 | RD | -========= -=========== -=========== | WR | -= -= ------------= ______________________________________________________________________________ Writer | RD | ---------============= | WR | -====================== ______________________________________________________________________________ - thread waits for lock = thread has lock
Subscribe to:
Posts (Atom)