summaryrefslogtreecommitdiffstats
path: root/lurker/libesort/Transaction.cpp
blob: df8eba0b1d5e934d66e152633c320803e1955759 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
/*  $Id: Transaction.cpp 1649 2009-10-19 14:35:01Z terpstra $
 *  
 *  Transaction.cpp - Write buffer for a commit
 *  
 *  Copyright (C) 2002 - Wesley W. Terpstra
 *  
 *  License: GPL
 *  
 *  Authors: 'Wesley W. Terpstra' <wesley@terpstra.ca>
 *  
 *    This program is free software; you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation; version 2.
 *    
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *    
 *    You should have received a copy of the GNU General Public License
 *    along with this program; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#define _FILE_OFFSET_BITS 64
  
#include "io.h"
#include "Transaction.h"
#include "esort.h"

#include <iostream>
#include <cassert>
#include <cstring>

/* #define DEBUG */

namespace ESort
{

Transaction::Transaction(int fd_, const Parameters* p_)
 : fd(fd_), p(p_), buf(new unsigned char[p->blockSize()]), 
   eof(buf + p->blockSize() - 2*(p->keyWidth() + 1)), off(buf)
{
}

Transaction::~Transaction()
{
	delete [] buf;
}

int Transaction::dump()
{
//	std::cout << "BLOCK WRITE" << std::endl;
	
	ssize_t out = ::write(fd, buf, p->blockSize());
	if (out != (ssize_t)p->blockSize())
	{
#ifdef DEBUG
		perror(__FILE__ ":" #__LINE__ ":write");
#endif
		return -1;
	}
	
	return 0;
}

int Transaction::write(long len, int dup, const char* key)
{
	assert (dup < 256);
	
//	std::cout << "Write: " << len << " - " << dup << " - " << key << std::endl;
	
	long fragment = len - dup;
	
	if (off + fragment > eof)
	{	// would overflow this block
		for (unsigned int i = 0; i < p->keyWidth(); ++i)
			off[i] = 0;
		off[p->keyWidth()] = 1; // (0, 1) is eof marker
		
		if (dump() != 0) return -1;
		off = buf;
		
		// first key has 0 compression
		dup = 0;
		fragment = len;
	}
	
	for (int i = p->keyWidth()-1; i >= 0; --i)
	{
		((unsigned char*)off)[i] = len;
		len >>= 8;
	}
	
	off += p->keyWidth();
	*off = dup;
	++off;
	
	memcpy(off, key+dup, fragment);
	off += fragment;
	
//	std::cout << "Position: " << long(off - buf) << " from 0." << std::endl;
	
	return 0;
}

int Transaction::finish()
{
	if (off != buf)
	{
		for (unsigned int i = 0; i < p->keyWidth(); ++i)
			off[i] = 0;
		off[p->keyWidth()] = 1; // (0, 1) is eof marker
		
		if (dump() != 0) return -1;
	}
	
	if (p->synced())
		return fsync(fd);
	else	return 0;
}

}