-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathhash.cpp
More file actions
235 lines (193 loc) · 10.6 KB
/
hash.cpp
File metadata and controls
235 lines (193 loc) · 10.6 KB
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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
#include "hash.h"
#include <iostream>
#include <utility>
#include <math.h>
bool compare(const std::pair<int, int>&i, const std::pair<int, int>&j) {
return i.first < j.first;
}
void iniciaHash(int quant_reg, std::string tabela, std::string campo) {
FILE* arquivo; //ponteiro para arquivo
int tam = ceil((1.0*quant_reg / TAM_BLOCO)/0.6); //quant de bloco
long int pos_bloco = 0; //auxiliar para preencher o arquivo
long int hash[tam]; //ira guardar o endereco de cada bloco do arquivo
std::string nome_arq = (tabela + "_HASH_" + campo + ".bin"); //nome do arquivo - "tabela_campo_HASH.bin"
bloco block; //bloco auxliar pra preencher arquivo com os blocos iniciais
block.prox = -1; //-1 indicando a inexistencia de um bloco adicional
block.num_elem = 0; //0 pois os blocos começam vazios
//escreve tam e escreve um long int = 0 tam vezes
arquivo = fopen(nome_arq.c_str(), "wb+");
fseek(arquivo,0,SEEK_SET);
fwrite(&tam,sizeof(int),1,arquivo); //escreve quantos blocos tem na hash
for(int i=0; i<tam;i++)
fwrite(&pos_bloco,sizeof(long int), 1, arquivo); //escreve tam vezes um long que int que ira...
fclose(arquivo); //...ira indicar a posicao de cada bloco no arquivoo
//escreve os blocos no arquivo e atualiza o vetor hash com a posicao no arquivo de cada bloco
arquivo = fopen(nome_arq.c_str(), "ab"); //abre o arquivo com append binario
for (int i=0; i<tam;i++) { //itera tam vezes:
hash[i] = ftell(arquivo); //escrevendo em hash[i] a posicao que o bloco sera escrito no arquivo
fwrite(&block,sizeof(bloco),1,arquivo); //escreve bloco aux no arquivo tam vezes
}
fclose(arquivo); //fecha o arquivo
// atualiza os long int com a posicao de cada bloco escrito anteriormente (que esta guardado em hash[i])
arquivo = fopen(nome_arq.c_str(), "rb+"); //abre o arquivo
for (int i=0; i<tam;i++) { //itera tam vezes:
fseek(arquivo,sizeof(int) + i*sizeof(long int),SEEK_SET); //com o offset do primeiro int escrito (linha 19) anda passos de tamanho long int
fwrite(&hash[i],sizeof(long int),1,arquivo); //escrevendo no arquivo a posicao que os blocos foram escritos no arquivo
}
fclose(arquivo); //fecha o arquivo
}
long int buscaHash(std::string tabela, std::string campo, int chave) {
FILE* arquivo;
std::string nome_arq = (tabela + "_HASH_" + campo + ".bin"); //nome do arquivo
int tam_hash; //tamanho da hash, necessario para usar no modulo da funcao hash
int pos_hash; //indica qual posicao a funcao hash retornou
long int pos_bloco; //indica qual posicao a hash aponta
arquivo = fopen(nome_arq.c_str(),"rb"); //abre o arquivo para leitura binaria
if (arquivo == NULL)
std::cout << "Erro ao abrir o arquivo." << std::endl;
fseek(arquivo,0,SEEK_SET);
fread(&tam_hash,sizeof(int),1,arquivo); //le tamanho da hash
fclose(arquivo);
// std::cout << chave << ' ' << tam_hash << '\n';
pos_hash = (chave * 127) % tam_hash; //executa a func. hash obtendo a pos do vetor hash
// std::cout << "POS_HASH - " << pos_hash << '\n';
arquivo = fopen(nome_arq.c_str(),"rb");
fseek(arquivo,sizeof(int) + pos_hash*sizeof(long int),SEEK_SET); //vai até o endereco pos_ash
fread(&pos_bloco,sizeof(long int),1,arquivo); //pega o endereco do bloco apontado por pos_hash
fclose(arquivo);
return pos_bloco;
}
void insereHash(std::string tabela, std::string campo, std::pair<int,int> el, long int pos_bloco ) {
FILE* arquivo;
bloco prim_bloco;
std::string nome_arq = tabela + "_HASH_" + campo + ".bin"; //nome do arquivo
arquivo = fopen(nome_arq.c_str(),"rb+"); //abre pra leitura e escrita sem sobrescrever o arquivo
fseek(arquivo,pos_bloco,SEEK_SET);
fread(&prim_bloco,sizeof(bloco),1,arquivo); //le o bloco apontado por pos_bloco
if (prim_bloco.num_elem < TAM_BLOCO) { //se o bloco nao estiver cheio
prim_bloco.elemento[prim_bloco.num_elem] = el; //insere o par no vetor
prim_bloco.num_elem++; //atualiza o preenchimento do vetor
fseek(arquivo,pos_bloco,SEEK_SET); //como houve um fread que após a leitura anda com o ponteiro, é preciso voltar novamente ao pos_bloco
fwrite(&prim_bloco,sizeof(bloco),1,arquivo); //sobrescreve o bloco com as infos atualizadas
fclose(arquivo);
}
else if(prim_bloco.prox == -1) { //se nao tiver um proximo bloco
bloco novo_bloco; //cria um novo bloco
fseek(arquivo,0,SEEK_END); //vai para o final do arquivo
prim_bloco.prox = ftell(arquivo); //atualiza o bloco.prox do primeiro para apontar para final do arquivo (onde ira ser inserido o proximo bloco)
novo_bloco.prox = -1; //novo bloco aponta pra nenhum bloco
novo_bloco.elemento[0] = el; //ja insere o el no novo bloco
novo_bloco.num_elem = 1; //e atualiza o numero de elementos em 1
fwrite(&novo_bloco,sizeof(bloco),1,arquivo); //escreve o novo bloco no final do arquivo
fseek(arquivo,pos_bloco,SEEK_SET); //volta para a posicao do primeiro bloco
fwrite(&prim_bloco,sizeof(bloco),1,arquivo); //sobrescreve o primeiro bloco com o novo bloco.prox
fclose(arquivo);
}
else { //se o bloco esta cheio, e existe um proximo bloco
insereHash(tabela,campo,el,prim_bloco.prox); //chamamos a insercao nesse novo bloco
}
}
std::vector<bloco> leHash(std::string tabela, std::string campo, int chave) {
FILE* arquivo;
std::vector<bloco> block;
bloco aux;
std::string nome_arq = tabela + "_HASH_" + campo + ".bin"; //nome do arquivo
long int pos_bloco = buscaHash(tabela,campo,chave); //pega a pos_bloco referente a chave
arquivo = fopen(nome_arq.c_str(),"rb"); //abre o arquivo para leitura
fseek(arquivo,pos_bloco,SEEK_SET); //move o ponteiro para pos_bloco
fread(&aux,sizeof(bloco),1,arquivo); // le o bloco para um auxiliar...
block.push_back(aux); //e o insere no vector de blocos
while(aux.prox != -1){ //enquanto aux.prox apontar para um novo bloco
fseek(arquivo,aux.prox,SEEK_SET); //iremos ate aux.prox
fread(&aux,sizeof(bloco),1,arquivo); //atualizaremos aux com esse novo bloco
block.push_back(aux); //o inserimos para o vector de blocos
}
return block;
}
void removeHash(std::string tabela, std::string campo) {
std::string nome_arq = tabela + "_HASH_" + campo + ".bin"; //nome do arquivo
int status = remove(nome_arq.c_str());
if (status == 0)
std::cout << "o arquivo: \"" << nome_arq << "\" foi deletado com sucesso." << std::endl;
else
std::cout << "Nao foi possivel deletar o arquivo" << std::endl;
}
int buscaPonteiroU(std::string tabela, std::string campo, int elemento) {
// pega bloco da hash
std::vector<bloco> busca = leHash("tabelas/" + tabela, campo, elemento);
for (int i = 0; i < busca.size(); i++) {
for (int j = 0; j < busca[i].num_elem; j++) {
if (busca[i].elemento[j].first == elemento) { // encontrou chave
return busca[i].elemento[j].second; // retorna ponteiro
}
}
}
return -1;
}
std::vector<int> buscaPonteiroN(std::string tabela, std::string campo, int elemento) {
// pega bloco da hash
std::vector<bloco> busca = leHash("tabelas/" + tabela, campo, elemento);
std::vector<int> ponteiros; // vector de ponteiros onde a busca foi encontrada
for (int i = 0; i < busca.size(); i++) {
for (int j = 0; j < busca[i].num_elem; j++) {
if (busca[i].elemento[j].first == elemento) { // encontrou chave
ponteiros.push_back(busca[i].elemento[j].second); // add ponteiro
}
}
}
return ponteiros;
}
int buscaPonteiroU(std::string tabela, std::string campo, int elemento) {
// pega bloco da hash
std::vector<bloco> busca = leHash("tabelas/" + tabela, campo, elemento);
for (int i = 0; i < busca.size(); i++) {
for (int j = 0; j < busca[i].num_elem; j++) {
if (busca[i].elemento[j].first == elemento) { // encontrou chave
return busca[i].elemento[j].second; // retorna ponteiro
}
}
}
return -1;
}
std::vector<int> buscaPonteiroN(std::string tabela, std::string campo, int elemento) {
// pega bloco da hash
std::vector<bloco> busca = leHash("tabelas/" + tabela, campo, elemento);
std::vector<int> ponteiros; // vector de ponteiros onde a busca foi encontrada
for (int i = 0; i < busca.size(); i++) {
for (int j = 0; j < busca[i].num_elem; j++) {
if (busca[i].elemento[j].first == elemento) { // encontrou chave
ponteiros.push_back(busca[i].elemento[j].second); // add ponteiro
}
}
}
return ponteiros;
}
/*
int main(){
std::string tab = "tabela";
std::string camp = "campo";
std::vector<bloco> bl;
iniciaHash(20,tab,camp);
for(int i = 0; i<20;i++){
std::pair<int, int > a;
a.first = (i+1)*10;
a.second = 99-i;
//std::cout << a.first << " ";
insereHash("tabela","campo",a, buscaHash(tab,camp,a.first));
}
std::cout << "pos insercao > " << std::endl << std::endl;
for(int i=0; i<20; i++){
std::vector<bloco> blocos;
blocos = leHash(tab,camp,(i+1)*10);
for(int j = 0; j<blocos.size();j++){
std::cout << " [CHAVE " << i << ", BLOCO " << j << "] - ";
for(int k = 0; k<blocos[j].num_elem;k++){
std::cout << "[" << blocos[j].elemento[k].first << "," << blocos[j].elemento[k].second << "], ";
}
std::cout << std::endl;
}
}
removeHash(tab,camp);
return 0;
}
*/