1 /*
2 * Copyright (C) 2021 Jakub Kruszona-Zawadzki, Core Technology Sp. z o.o.
3 *
4 * This file is part of MooseFS.
5 *
6 * MooseFS is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, version 2 (only).
9 *
10 * MooseFS is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with MooseFS; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02111-1301, USA
18 * or visit http://www.gnu.org/licenses/gpl-2.0.html
19 */
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include <inttypes.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <syslog.h>
29
30 #include "main.h"
31 #include "cfg.h"
32 #include "datapack.h"
33
34 typedef struct mlogentry {
35 uint64_t chunkid;
36 uint32_t inode;
37 uint32_t indx;
38 uint8_t type;
39 } mlogentry;
40
41 static mlogentry *mloghash;
42 static mlogentry *mloghashprev;
43 static uint32_t mloghashsize;
44 static uint32_t mloghashprevsize;
45 static uint32_t mloghashelements;
46 static uint32_t mloghashprevelements;
47 static uint32_t mloghashcapacity;
48 static uint8_t blocked;
49
missing_log_insert(uint64_t chunkid,uint32_t inode,uint32_t indx,uint8_t type)50 void missing_log_insert(uint64_t chunkid,uint32_t inode,uint32_t indx,uint8_t type) {
51 uint32_t hash,disp;
52 if (blocked || mloghashelements>=mloghashcapacity || chunkid==0) {
53 return;
54 }
55 hash = (((inode * 1363546567) ^ indx) * 985732289) ^ chunkid;
56 disp = (((inode * 2345123993) + indx) * 746344009) + chunkid;
57 hash %= mloghashsize;
58 disp %= mloghashsize;
59 disp |= 1;
60 while (mloghash[hash].chunkid!=0) {
61 if (mloghash[hash].chunkid==chunkid && mloghash[hash].inode==inode && mloghash[hash].indx==indx) {
62 return;
63 }
64 hash += disp;
65 hash %= mloghashsize;
66 }
67 mloghash[hash].chunkid = chunkid;
68 mloghash[hash].inode = inode;
69 mloghash[hash].indx = indx;
70 mloghash[hash].type = type;
71 mloghashelements++;
72 }
73
missing_log_swap(void)74 void missing_log_swap(void) {
75 mlogentry *mloghashtmp;
76
77 if (blocked) {
78 blocked = 0;
79 } else {
80 if (mloghashsize == mloghashprevsize) {
81 mloghashtmp = mloghashprev;
82 mloghashprev = mloghash;
83 mloghash = mloghashtmp;
84 } else {
85 free(mloghashprev);
86 mloghashprev = mloghash;
87 mloghash = malloc(sizeof(mlogentry)*mloghashsize);
88 }
89 memset(mloghash,0,sizeof(mlogentry)*mloghashsize);
90 mloghashprevsize = mloghashsize;
91 mloghashprevelements = mloghashelements;
92 mloghashelements = 0;
93 }
94 }
95
missing_log_getdata(uint8_t * buff,uint8_t mode)96 uint32_t missing_log_getdata(uint8_t *buff,uint8_t mode) {
97 uint32_t i,j;
98 if (buff==NULL) {
99 return mloghashprevelements*((mode==0)?16:17);
100 } else {
101 j = 0;
102 for (i=0 ; i<mloghashprevsize && j<mloghashprevelements ; i++) {
103 if (mloghashprev[i].chunkid!=0) {
104 put64bit(&buff,mloghashprev[i].chunkid);
105 put32bit(&buff,mloghashprev[i].inode);
106 put32bit(&buff,mloghashprev[i].indx);
107 if (mode) {
108 put8bit(&buff,mloghashprev[i].type);
109 }
110 j++;
111 }
112 }
113 return 0;
114 }
115 }
116
missing_log_reload(void)117 void missing_log_reload(void) {
118 uint32_t ncapacity;
119
120 ncapacity = cfg_getuint32("MISSING_LOG_CAPACITY",100000);
121
122 if (ncapacity<1000) {
123 syslog(LOG_WARNING,"MISSING_LOG_CAPACITY to low - increased to 1000");
124 }
125 if (ncapacity>1000000) {
126 syslog(LOG_WARNING,"MISSING_LOG_CAPACITY to high - decreased to 1000000");
127 }
128
129 if (ncapacity != mloghashcapacity) {
130 if (mloghash!=NULL) {
131 free(mloghash);
132 }
133 for (mloghashsize=1024 ; mloghashsize<(ncapacity*3/2) ; mloghashsize<<=1) {
134 }
135 mloghash = malloc(sizeof(mlogentry)*mloghashsize);
136 memset(mloghash,0,sizeof(mlogentry)*mloghashsize);
137 mloghashelements = 0;
138 if (mloghashcapacity==0) {
139 blocked = 0;
140 } else {
141 blocked = 1;
142 }
143 mloghashcapacity = ncapacity;
144 }
145 }
146
missing_log_init(void)147 int missing_log_init(void) {
148 mloghash = NULL;
149 mloghashprev = NULL;
150 mloghashsize = 0;
151 mloghashprevsize = 0;
152 mloghashelements = 0;
153 mloghashprevelements = 0;
154 mloghashcapacity = 0;
155 blocked = 1;
156 missing_log_reload();
157 main_reload_register(missing_log_reload);
158 return 1;
159 }
160