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;
}
}
|