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