-- $Id: namenode.sql 289 2010-10-29 14:10:03Z gerd $

-- Database definition for the namenode database
-- This is for PostgreSQL 8.2 or better

CREATE TABLE datastore (
	id	 INTEGER NOT NULL,      -- The id in this database
	identity VARCHAR(64) NOT NULL,  -- The external id
	size     BIGINT NOT NULL,       -- number of blocks
	enabled  BOOLEAN NOT NULL,
	PRIMARY KEY (id),
	UNIQUE(identity)
) WITHOUT OIDS;

CREATE TABLE blockalloc (
	datastore  INTEGER REFERENCES datastore(id) ON DELETE CASCADE NOT NULL ,
	-- the datastore where the blocks are stored

	blkidx	  BIGINT NOT NULL,
	-- the first data block this record is about. Normally, this
        -- record is about 1024 blocks, i.e. the last block is
        -- blkidx+1023. However, if this exceeds the number of blocks
        -- on this node this record is about fewer blocks

	blkmap	  BIT VARYING(1024) NOT NULL,
	-- for every block this bit string says whether it is used (1)
        -- or free (0)
	
	blkcnt    INTEGER NOT NULL,
	-- the number of used blocks in blkmap

	PRIMARY KEY (datastore, blkidx)
) WITHOUT OIDS;

-- Look up whether [block] is free:
-- SELECT substring(blkmap FROM block & 1023 FOR 1) :: integer
-- WHERE datastore=... AND blkidx=block & (~1023)


--CREATE INDEX blockalloc_cnt ON blockalloc(datastore, blkcnt);
-- This index is useful to find range of blocks

CREATE TABLE inode (
	id	  BIGINT NOT NULL,        -- inode ID
	ftype     CHARACTER(1) NOT NULL,
	username  VARCHAR(64) NOT NULL,
	groupname VARCHAR(64) NOT NULL,
	mode	  INTEGER NOT NULL,
	eof	  BIGINT NOT NULL,
	mtime1    BIGINT NOT NULL,   -- seconds
	mtime2    INTEGER NOT NULL,  -- nanoseconds
	ctime1    BIGINT NOT NULL,   -- seconds
	ctime2    INTEGER NOT NULL,  -- nanoseconds
	blimit	  BIGINT NOT NULL,
	repfactor INTEGER NOT NULL,
	field1    TEXT NOT NULL,
	seqno     BIGINT NOT NULL,
	crverf    BIGINT NOT NULL,
	PRIMARY KEY(id)
) WITHOUT OIDS;

CREATE TABLE inodeblocks (
	inode     BIGINT REFERENCES inode(id) ON DELETE CASCADE NOT NULL,
	blkidx    BIGINT NOT NULL,
	datastore  INTEGER REFERENCES datastore(id) ON DELETE CASCADE NOT NULL,
	block     BIGINT NOT NULL,
	-- Stores the [block] for [blkidx].

	PRIMARY KEY(inode, blkidx, datastore)
) WITHOUT OIDS;

CREATE TABLE checksums (
        inode     BIGINT REFERENCES inode(id) ON DELETE CASCADE NOT NULL,
	blkidx    BIGINT NOT NULL,
	cksum     VARCHAR(255),
	PRIMARY KEY(inode, blkidx)
) WITHOUT OIDS;

CREATE TABLE names (
       inode_d    BIGINT REFERENCES inode(id) NOT NULL,
       name       TEXT NOT NULL,
       inode      BIGINT REFERENCES inode(id) NOT NULL, -- no cascade!
       PRIMARY KEY (inode_d, name)
) WITHOUT OIDS;
-- inode_d: the containing directory
-- name: the file in the directory
-- inode: the inode of the file

CREATE INDEX names_inode_d ON names(inode_d);
-- for listing directories

CREATE INDEX names_inode ON names(inode);
-- for reverse lookups

CREATE TABLE revision (
	revstr	  VARCHAR(64) NOT NULL
	--iscoord   BOOLEAN
	-- if this node was the last time the coordinator, all pending
    	-- transactions must be committed, at startup. So we have to
   	-- remember this. NULL if not meaningful.
) WITHOUT OIDS;

INSERT INTO revision (revstr) 
VALUES ('00000000000.000000000-0102030405060708090a0b0c0d0e0f');

-- insert "/"
INSERT INTO inode (id,ftype,username,groupname,mode,eof,mtime1,mtime2,
       	    	   ctime1,ctime2,blimit,repfactor,field1,seqno,crverf)
VALUES (1,'d','root','root',493,0,0,0,0,0,0,1,'',0,0);

--INSERT INTO names (inode_d, name,inode)
--VALUES (1, '/', 1);
