Commit b31ddc86 authored by Siddharth Aggarwal's avatar Siddharth Aggarwal

Initial checkin of disk checkpointing code. Trie merge doesn't work correctly yet

parent 97f3da16
# $FreeBSD: src/sbin/shdconfig/Makefile,v 1.2.10.1 2001/04/25 10:58:12 ru Exp $
PROG= shdconfig
SRCS= shdconfig.c trie.c
CFLAGS+= -I${.CURDIR}/../../sys -g
LDADD+= -lkvm
DPADD+= ${LIBKVM}
BINGRP= kmem
BINMODE= 2555
.include <bsd.prog.mk>
#include "trie.h"
#include "block_alloc.h"
void SetShadowSize (long size)
{
shadow_size = size;
}
void InitBlockAllocator (int method, long range_start, long range_size)
{
reclaim_method = method;
block_range.start = range_start;
block_range.end = range_start + range_size;
block_range.ptr = range_start;
printf ("Initialized block allocator to start = %ld, end = %ld\n", block_range.ptr, block_range.end);
SetShadowSize (range_size);
}
void DeleteCheckpoint (int version)
{
/* dummy function. write code to merge checkpoints */
return;
}
void CopyTree (Trie * trie, long size)
{
/* dummy function. Iterate through the trie and adjust each block
number by "size". Also Copy the blocks to new locations respectively */
if (0 != trie)
{
TrieIterator pos;
}
}
long GetLastBlock ()
{
/* dummy function. Returns the largest block number allocated to
a given checkpoint */
return 0;
}
long CurrentFreeBlockSize ()
{
if (block_range.end < block_range.ptr)
return (block_range.ptr + shadow_size - block_range.end);
else
return (block_range.end - block_range.ptr);
}
int BlockFree (long start, long end)
{
/* called only for EXPLICIT_CKPT_DELETE. Shouldn't be called for
LAST_CKPT_AUTO_DELETE at all */
struct FreeSpaceQueue* temp = head;
while (temp != 0)
{
if (temp->start == (end + 1) % shadow_size)
{
temp->start = start;
return 0;
}
else
if ((temp->end + 1) % shadow_size == start)
{
temp->end = end;
return 0;
}
temp = temp->next;
}
AddFreeSpaceToQueue (start, end);
return 0;
}
long BlockAlloc (int size)
{
struct FreeSpaceQueue* temp = 0;
long retVal;
printf ("\nCalling BlockAlloc\n");
switch (reclaim_method)
{
case LAST_CKPT_AUTO_DELETE:
while (CurrentFreeBlockSize () < size)
{
DeleteCheckpoint (first_checkpoint);
block_range.end = GetLastBlock (first_checkpoint);
/* Delete the corresponding trie and merge changes with
next checkpoint */
first_checkpoint++;
}
break;
case EXPLICIT_CKPT_DELETE:
while (CurrentFreeBlockSize () < size)
{
printf ("size = %d, free_block_size = %d\n", size, CurrentFreeBlockSize());
printf ("end = %ld, ptr = %ld\n", block_range.end, block_range.ptr);
if (-1 == MergeWithNextFreeBlockRange ( CurrentFreeBlockSize() ))
{
printf ("Error! No more free space on disk\n");
return -1;
}
}
break;
}
retVal = block_range.ptr;
block_range.ptr += size;
printf ("Allocating %d blocks starting %d\n", size, retVal);
return retVal;
}
long MergeWithNextFreeBlockRange (long size)
{
int done = 0;
Trie * trie;
struct FreeSpaceQueue* temp = GetNextFreeSpaceFromQueue ();
if (0 == temp)
return -1;
while (1)
{
CopyTree (trie, size);
if ((GetLastBlock() + size) % shadow_size >= temp->start)
{
block_range.start = block_range.ptr = GetLastBlock();
block_range.end = temp->end;
DeleteFreeSpace (temp);
break;
}
}
return (size + temp->end - temp->start);
}
int initFreeSpaceQueue (void)
{
head = tail = 0;
}
int AddFreeSpaceToQueue (long start, long end)
{
struct FreeSpaceQueue* new = malloc (sizeof (struct FreeSpaceQueue), M_DEVBUF, M_NOWAIT);
new->start = start;
new->end = end;
if (0 == head)
head = tail = new;
else
{
new->next = head;
head->prev = new;
head = new;
}
return 0;
}
struct FreeSpaceQueue* GetNextFreeSpaceFromQueue (void)
{
struct FreeSpaceQueue* temp = 0;
if (0 == tail)
return 0;
else
{
temp = tail;
tail = tail->prev;
}
return temp;
}
int PrintFreeSpaceQueue()
{
struct FreeSpaceQueue* current = head;
while (current != 0)
{
printf ("%ld %ld\n", current->start, current->end);
current = current->next;
}
return 0;
}
int DeleteFreeSpace (struct FreeSpaceQueue* temp)
{
if (head == temp)
head = 0;
free (temp, M_DEVBUF);
temp = temp->next = temp->prev = 0;
return 0;
}
int main ()
{
struct FreeSpaceQueue* temp;
AddFreeSpaceToQueue (10, 15);
AddFreeSpaceToQueue (2, 4);
PrintFreeSpaceQueue();
temp = GetNextFreeSpaceFromQueue();
printf ("%d %d\n", temp->start, temp->end);
DeleteFreeSpace (temp);
temp = GetNextFreeSpaceFromQueue();
printf ("%d %d\n", temp->start, temp->end);
DeleteFreeSpace (temp);
PrintFreeSpaceQueue();
return 0;
}
/* Change to correct value */
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/proc.h>
#include <sys/buf.h>
#include <sys/malloc.h>
#include <sys/namei.h>
#include <sys/conf.h>
#include <sys/stat.h>
#include <sys/sysctl.h>
#include <sys/disklabel.h>
#include <ufs/ffs/fs.h>
#include <sys/devicestat.h>
#include <sys/fcntl.h>
#include <sys/vnode.h>
#define LAST_CKPT_AUTO_DELETE 1
#define EXPLICIT_CKPT_DELETE 2
#define SRC_TO_SHADOW 1
#define SHADOW_TO_SRC 2
int first_checkpoint;
int reclaim_method;
long shadow_size;
struct CurrentFreeBlockRange
{
long start;
long end;
long ptr;
} block_range;
struct FreeSpaceQueue
{
long start;
long end;
struct FreeSpaceQueue *next;
struct FreeSpaceQueue *prev;
} *head, *tail;
void SetShadowSize (long size);
void InitBlockAllocator (int method, long range_start, long range_size);
void DeleteCheckpoint (int version);
void CopyTree (Trie * trie, long size);
long GetLastBlock ();
long CurrentFreeBlockSize ();
int BlockFree (long start, long end);
long BlockAlloc (int size);
long MergeWithNextFreeBlockRange (long size);
int initFreeSpaceQueue (void);
int AddFreeSpaceToQueue (long start, long end);
struct FreeSpaceQueue* GetNextFreeSpaceFromQueue (void);
int PrintFreeSpaceQueue();
int DeleteFreeSpace (struct FreeSpaceQueue* temp);
This diff is collapsed.
#define NSHD 1
This diff is collapsed.
This diff is collapsed.
#ifndef TRIE_H_TRIE_1
#define TRIE_H_TRIE_1
#define KERNEL
#ifdef KERNEL
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/proc.h>
#include <sys/buf.h>
#include <sys/malloc.h>
#include <sys/namei.h>
#include <sys/conf.h>
#include <sys/stat.h>
#include <sys/sysctl.h>
#include <sys/disklabel.h>
#include <ufs/ffs/fs.h>
#include <sys/devicestat.h>
#include <sys/fcntl.h>
#include <sys/vnode.h>
#else
#include <stdio.h>
#include <stdlib.h>
#endif
/*--------------
WARNING!!!!
--------------
The insertion functions are currently not transactional.*/
/* To change what the TrieKey and TrieValue types are, change the two
typedefs and then change the definition of the two functions.
TrieKey must not have a sign-extending shift.*/
typedef unsigned int TrieKey;
TrieKey getDefaultTrieKey(void);
typedef int TrieValue;
TrieValue getDefaultTrieValue(void);
/* pick one */
enum
{
BITS_PER_LEVEL = 1
/* Don't pick the below options at this time. I'm assuming the first
one for reasons of simplification, and because it provides the most
compression. */
/* BITS_PER_LEVEL = 2 */
/* BITS_PER_LEVEL = 4 */
};
enum
{
CHILD_COUNT = (1 << BITS_PER_LEVEL),
TOTAL_BITS = sizeof(TrieKey) * 8,
LEVEL_MASK = 0xffffffff >> (TOTAL_BITS - BITS_PER_LEVEL),
TOTAL_LEVELS = TOTAL_BITS / BITS_PER_LEVEL
};
typedef struct TrieNodeTag
{
char depth;
char maxDepth;
short isLeaf;
TrieKey key;
TrieValue value;
struct TrieNodeTag * next;
/* Don't touch these */
struct TrieNodeTag * parent;
struct TrieNodeTag * child[CHILD_COUNT];
} TrieNode;
typedef void * FirstPtrT;
typedef void * SecondPtrT;
typedef void * ThirdPtrT;
typedef int (*BlockAllocateFunction)(int);
typedef int (*BlockFreeFunction)(int, int);
typedef int (*BlockCopyFunction)(FirstPtrT, SecondPtrT,
TrieKey source, TrieValue dest,
int size, int type);
typedef struct
{
TrieNode root;
BlockAllocateFunction blockAlloc;
BlockFreeFunction blockFree;
BlockCopyFunction blockCopy;
FirstPtrT first;
SecondPtrT second;
ThirdPtrT third;
TrieNode * tail;
} Trie;
typedef TrieNode * TrieIterator;
/* Call init before doing anything else. Send a pointer to a valid Trie *
So it can allocate and setup a Trie for you and point your
pointer to it.
Returns 1 on success, 0 on failure */
int TrieInit(Trie ** trieOutPtr, BlockAllocateFunction blockAlloc,
BlockFreeFunction blockFree, BlockCopyFunction blockCopy);
/* Call cleanup before exiting. Destroys the Trie. */
void TrieCleanup(Trie * triePtr);
/* Output the structure of the tree to stderr */
void logTrieStructure(Trie * triePtr);
/* Initialize an iterator based on a trie. Starts at the beginning.
Send a pointer to a valid TrieIterator * so an iterator can be
allocated.
Returns 1 on success, 0 on failure */
int TrieIteratorInit(Trie * triePtr, TrieIterator * iterator);
void TrieIteratorCleanup(TrieIterator * iterator);
/* Move the TrieIterator to the next position. */
void TrieIteratorAdvance(TrieIterator * iterator);
/* Checks to see if the iterator points to a valid node.
If the iterator is valid, this returns 1, otherwise 0. */
int TrieIteratorIsValid(TrieIterator iterator);
/* Inserts every key in [key, key+size) and skips any of these
keys which are already inserted. This is transactional. If any insert
fails, they all fail.
Returns the number of keys actually inserted (non-skipped inserts).
Returns <0 on failure */
int TrieInsertWeak(Trie * triePtr, TrieKey key, int size, FirstPtrT first,
SecondPtrT second, ThirdPtrT third);
/* Inserts every key in [key, key+size) and overwrites any of these
keys which are already inserted. This inserts 'value' at key, 'value+1'
at key+1, etc. up to size. This is transactional. If any of the inserts
fail, they all fail.
Returns the number of new keys inserted (non-overwrite inserts).
Returns <0 on failure. */
int TrieInsertStrong(Trie * triePtr, TrieKey key, int size, TrieValue value);
/* This is not transactional.
The return value determines whether it succeeded or not.
1 for success, 0 for failure. */
int merge(Trie * dest, Trie * source);
/* This is not transactional. */
void freeAllBlocks(Trie * trie);
int depthToSize(int num);
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment