This is a POD file. If you prefer reading a man page, run `perldoc ./HACKING`. Or use `pod2text HACKING` to generate an easier to read text file. Both of these programs should come with a default Perl installation. =head1 DEBUGGING =head2 General Any debugging messages are written to C<~/.ncdc/stderr.log>. Note that this file is emptied every time ncdc starts up, so be sure to either make backups or check the contents of the log file before this happens! Messages starting with C almost always indicate a bug. If you find one, please report it! Messages starting with C can happen both because something unexpected happened or because of a bug. If you see such a message along the lines of "assertion failure" or "line should not be reached", then this always indicates a bug. By default, debug-level messages are not logged, enable the I setting within ncdc to get these as well. Be warned, however, that depending on how you use ncdc, this may generate a lot of data. My ncdc generates about 1 GiB per week, for instance. =head2 GDB GDB can be used to debug various kinds of crashes (but not all of them), deadlocks or to find out exactly when a C or C message is being logged. Note that you usually want ncdc to be compiled with debugging symbols when using GDB. Compile as follows: ./configure CFLAGS=-g && make clean && make How you run gdb depends on the kind of problem you are experiencing. Here are some tips for various situations: =over =item ncdc crashes shortly after startup. The easiest way is to just start ncdc within gdb directly. $ gdb /path/to/ncdc [..] > run =item ncdc crashes after I perform a certain action. Running ncdc within gdb as above is in that case not very optimal, since the gdb messages may garble the screen and make it annoying to use ncdc. In this case it's easier attach gdb to a running ncdc. To do so, run ncdc as you usually would, and then run the following in a different terminal: $ gdb /path/to/ncdc $ncdc_pid [..] > continue =item ncdc crashes randomly after a long period of time. In this case it may be easier to use core dumps, as follows: $ ulimit -c unlimited $ ncdc # run ncdc as you usually would [let it crash] $ gdb /path/to/ncdc core =back The above tips work nice for debugging crashes, but gdb can also be used to debug when a C or C message is logged. Run ncdc with the I environment variable set to either I or I. For example, the following will let ncdc crash as soon as a C message is logged. $ G_DEBUG=fatal-warnings /path/to/ncdc If you happened to get gdb to see the crash, then you can use gdb commands to fetch more information on the crash. There are many online resources on debugging using gdb, but here are a few important commands: =over =item bt Get a backtrace. =item info threads List the active threads. =item thread $number Switch to another thread. =back In the off chance that you happened to have found a deadlock, these are easiest to debug by attaching gdb to a deadlocked ncdc. Running ncdc within gdb or using core dumps isn't very useful in these situations. =head2 Valgrind Valgrind can be used to debug crashes for which GDB fails. Bugs caused by incorrect handling of memory are very easily detected with valgrind. A major downside, however, is that ncdc takes approximately 10 times as much memory and is 10 times slower than when run natively or in GDB. As with GDB, make sure you have ncdc compiled with debugging symbols. To run ncdc in valgrind, use the following command: $ G_DEBUG=gc-friendly G_SLICE=always-malloc valgrind --leak-check=full\ --num-callers=25 --log-file=valgrindlog /path/to/ncdc And any issue valgrind can find will be written to the file 'valgrindlog'. Note that some of the reported problems, especially memory leaks, may not necessarily come from ncdc itself, but are harmless issues within glib or other libraries. =head1 IDENTIFIERS Ncdc uses all kinds of identifiers internally, let's explain some of them. =over =item hubid A "hub id" is 64bit integer that uniquely identifies a hub. The number is randomly generated and assigned upon the first run of C for a hub with that name. The use of hub IDs allow a user to change the name of a hub tab without compromising any other IDs or related configuration. =item CID / PID These are defined in the ADC spec. A CID uniquely identifies a user across multiple hubs, but only works on the ADC protocol. Ncdc doesn't try to assign a CID to users on NMDC hubs. =item uid A user id, internal to ncdc. This uniquely identifies a single user on a single hub. It's a 64bit unsigned integer, generated by taking the first 8 bytes of a tiger hash. The data that is hashed depends on the protocol, for ADC it's C, where C is the base32-encoded CID of the user. For NMDC, it's C, where C is the name of the user as sent by the hub (thus in the encoding that the hub uses). In both cases, the byte representation of is hashed, so these IDs are dependent on the byte order of the CPU architecture. This ID is used everywhere where a user should be identified, and is also stored on disk in the database file (in the download queue) and are used as the filename for user file lists in the C directory. They are usually represented in ASCII as 16-character HEX values. =back =head1 SQLITE SCHEMA This is the SQL schema used to store stuff in the db.sqlite3 file. C is set to 1. Note that this schema does not include foreign key clauses or other checks, in order to improve portability with older SQLite versions. =head2 Config & variables CREATE TABLE vars ( name TEXT NOT NULL, hub INTEGER NOT NULL DEFAULT 0, value TEXT NOT NULL, PRIMARY KEY(name, hub) ); Stores key-value pairs for configuration data and various other variables that need to be kept around for more than a single run. For global variables, C is 0. For hub-local variables, C is a random 64-bit integer. It is treated as unsigned in the code, but stored signed in the database. For every existing value of C, there should be a I key indicating the name that belongs to the hub tab, including the preceding C<#> character. CREATE TABLE share ( name TEXT NOT NULL PRIMARY KEY, path TEXT NOT NULL ); Stores the shared directories. C is the virtual name, C is the absolute filesystem path obtained by C. CREATE TABLE users ( hub INTEGER NOT NULL, uid INTEGER NOT NULL, nick TEXT NOT NULL, flags INTEGER NOT NULL ) Stores information about "special" users. Currently only used for users who are granted a slot. The C column is set, but its value is not currently used. Matching is instead done on the C column. C is a bit mask of flags, the flag for a granted slot is 1. =head2 Hash data CREATE TABLE hashdata ( root TEXT NOT NULL PRIMARY KEY, size INTEGER NOT NULL, tthl BLOB NOT NULL ); Unsurprisingly, this stores the hash data of shared files. C is the TTH root, encoded in base32. C is the size of the file and C is the TTH data. CREATE TABLE hashfiles ( id INTEGER PRIMARY KEY, filename TEXT NOT NULL UNIQUE, tth TEXT NOT NULL, lastmod INTEGER NOT NULL ); A mapping of I to I. The C column is an alias for the SQLite C, and used internally in ncdc to speed up certain operations. C is the absolute and canonical path to the file, as obtained from C. C refers to C, and C is the last modification time, as a UNIX timestamp. It is not uncommon to have multiple files with the same TTH. An row in C should B have a corresponding row in C. It is possible to have an row in C with no row in C referring to it, or to have entries in C that are not in a shared directory at all. These are cleaned up with C. =head2 Download queue CREATE TABLE dl ( tth TEXT NOT NULL PRIMARY KEY, size INTEGER NOT NULL, dest TEXT NOT NULL, priority INTEGER NOT NULL DEFAULT 0, error INTEGER NOT NULL DEFAULT 0, error_msg TEXT, tthl BLOB ); Each row represents a file in the download queue. File list downloads are not included. C is the base32-encoded TTH root of the file, C the file size, in bytes and C is the full destination path where the file will be moved to after downloading. Possible values for C are defined in the C macros in dl.c. Possible C values are defined in the C macros. C is NULL if there is no error. C is the downloaded TTH data, NULL if it hasn't been fetched yet. CREATE TABLE dl_users ( tth TEXT NOT NULL, uid INTEGER NOT NULL, error INTEGER NOT NULL DEFAULT 0, error_msg TEXT, PRIMARY KEY(tth, uid) ); Stores the users from which a download queue item can be downloaded from. C refers to C
, C is the user id, stored as a 64-bit signed integer but internally represented as an unsigned integer in ncdc. C and have the same meaning as for the C table, but obviously represent errors that only affect the user rather than the file. (e.g. when the file is not available from this user). It is possible for a C
row to have no corresponding rows in C, but a C row must always refer to a row in C
.