~drizzle-trunk/drizzle/development

1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
1
/* Copyright (c) 2008 PrimeBase Technologies GmbH, Germany
2
 *
3
 * PrimeBase Media Stream for MySQL
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation; either version 2 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * This program 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 this program; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
 *
19
 * Barry Leslie
20
 *
21
 * 2008-12-30
22
 *
23
 * H&G2JCtL
24
 *
25
 * BLOB alias index.
26
 *
27
 */
28
29
30
#ifndef __ALIAS_MS_H__
31
#define __ALIAS_MS_H__
32
#include <stddef.h>
33
1548.2.10 by Barry.Leslie at PrimeBase
Merge from trunk.
34
#include "defs_ms.h"
1548.2.2 by Barry.Leslie at PrimeBase
A lot of minor changes to clean up the code and to get it to build with Drizzle.
35
#include "cslib/CSStorage.h"
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
36
37
#define MS_ALIAS_FILE_MAGIC			0x5954228A
38
#define MS_ALIAS_FILE_VERSION		1
39
#define BLOB_ALIAS_LENGTH			1024
40
#define INVALID_ALIAS_HASH			((uint32_t)-1)
41
42
#ifdef HAVE_ALIAS_SUPPORT
43
class MSOpenTable;
44
class MSDatabase;
45
class CSHTTPOutputStream;
46
class MSMetaDataTable;
47
48
#define ACTIVE_ALIAS_INDEX "ms_blob_alias.idx"
49
50
#define NUM_RECORDS_PER_BUCKET	254		// 254 = bucket size of 4 K
51
#define BUCKET_LIST_SIZE		1024		
52
53
typedef struct MSAliasHead {
54
	CSDiskValue4			ah_magic_4;							/* Table magic number. */
55
	CSDiskValue2			ah_version_2;						/* The header version. */
56
	CSDiskValue2			ah_head_size_2;						/* The size of the header. */
57
	CSDiskValue8			ah_file_size_8;						/* The size of the file. */	
58
	
59
	CSDiskValue8			ah_free_list_8;						/* The offset of the first bucket in the free list. */
60
	
61
	CSDiskValue2			ah_num_buckets_2;					/* The number of bucket chains in the index. (BUCKET_LIST_SIZE when created)*/	
62
	CSDiskValue4			ah_bucket_size_4;					/* The size of each bucket. (NUM_RECORDS_PER_BUCKET when created)*/
63
64
} MSAliasHeadRec, *MSAliasHeadPtr;
65
66
/*
67
 * When a record is freed  ba_repo_id_4 is set to zero 
68
*/
69
typedef struct MSDiskAliasRec {
70
	CSDiskValue4			ar_repo_id_4;						/* File ID. Not zero when allocated. */
71
	CSDiskValue8			ar_offset_8;						/* Offset into the file of the BLOB. */
72
	CSDiskValue4			ar_hash_4;							/* The hash value of the alias string. (Is assumed to be at the end of the structure.*/
73
} MSDiskAliasRec, *MSDiskAliasPtr;
74
75
typedef struct MSADiskBucketHead {
76
	CSDiskValue8			ab_prev_bucket_8;					/* The file offset of the previouse bucket in the chain. */
77
	CSDiskValue8			ab_next_bucket_8;					/* The file offset of the next bucket in the chain. */
78
	CSDiskValue4			ab_num_recs_4;						/* The number of used record in the bucket. */
79
	CSDiskValue4			ab_eor_rec_4;						/* (End Of Records) The position of the first free record after all the records in the bucket. */
80
} MSADiskBucketHeadRec, *MSADiskBucketHeadPtr;
81
82
typedef struct MSADiskBucket {
83
	MSADiskBucketHeadRec	ab_heaher;
84
	MSDiskAliasRec			ab_records[NUM_RECORDS_PER_BUCKET];	/* The start of the records in the bucket. */
85
} MSADiskBucketRec, *MSADiskBucketPtr;
86
87
/*
88
 * MSABucketInfo stores bucket information in RAM.
89
 */
90
class MSABucketInfo: public CSOrderKey  {
91
public:
92
93
	MSABucketInfo(uint64_t offset, uint32_t num, uint32_t end_of_records): 
94
		bi_bucket_offset(offset),
95
		bi_records_offset(offset + offsetof(MSADiskBucketRec, ab_records)),
96
		bi_num_recs(num),
97
		bi_end_of_records(end_of_records),
98
		bi_NextLink(NULL),
99
		bi_PrevLink(NULL)
100
		{}
101
		
102
	uint64_t			bi_bucket_offset;	/* The file offset of the bucket. */
103
104
	uint64_t			bi_records_offset;	/* The file offset of the first record in the bucket. */
105
	
106
	// Required method for item in a CSLinkedList.
107
	virtual MSABucketInfo *getNextLink() { return bi_NextLink; }
108
	virtual MSABucketInfo *getPrevLink() { return bi_PrevLink; }
109
	virtual void setNextLink(CSObject *link) { bi_NextLink = (MSABucketInfo*)link; }
110
	virtual void setPrevLink(CSObject *link) { bi_PrevLink = (MSABucketInfo*)link; }
111
112
	virtual CSObject *getKey() { return this;}
113
	virtual int compareKey(CSOrderKey *x) {
114
		MSABucketInfo	*key = (MSABucketInfo *) x;
115
		
116
		if (bi_bucket_offset != key->bi_bucket_offset)
117
			return 0;
118
		
119
		return (bi_bucket_offset < key->bi_bucket_offset)? -1: 1;
120
	}
121
	
122
	static MSABucketInfo *newMSABucketInfo(uint64_t offset, uint32_t num = 0, uint32_t last = 0);
123
124
	uint32_t			getSize() { return bi_num_recs;}
125
	uint32_t			getEndOfRecords() { return bi_end_of_records;}
126
	void			recAdded(CSFile *iFile, uint32_t idx);
127
	void			recRemoved(CSFile *iFile, uint32_t idx, MSDiskAliasRec bucket[]);
128
	
129
private:
130
	// (bi_end_of_records -1) is the index of the last valid record in the bucket.
131
	// free records can actually appear any where in the bucket unless it has
132
	// just been compressed.
133
	uint32_t			bi_num_recs;		/* The number of records in the bucket. */
134
	uint32_t			bi_end_of_records;	/* The index of the start of the free records in the bucket. */
135
136
	MSABucketInfo	*bi_NextLink;
137
	MSABucketInfo	*bi_PrevLink;
138
};
139
140
class MSABucketLinkedList: public CSLinkedList {
141
public:
142
143
	/* Value is returned referenced. */
144
	MSABucketInfo *removeBack() { return (MSABucketInfo*) CSLinkedList::removeBack();}
145
146
	/* Value is returned NOT referenced. */
147
	MSABucketInfo *getBack(){ return (MSABucketInfo*) CSLinkedList::getBack();}
148
149
	/* Value is returned NOT referenced. */
150
	MSABucketInfo *getFront(){ return (MSABucketInfo*) CSLinkedList::getFront();}
151
152
	/* Value is returned referenced. */
153
	MSABucketInfo *removeFront(){ return (MSABucketInfo*) CSLinkedList::removeFront();}
154
};
155
156
typedef struct MSAliasRec {
157
	uint32_t			repo_id;	
158
	uint64_t			repo_offset;
159
	uint32_t			alias_hash;
160
} MSAliasRec, *MSAliasPtr;
161
162
class MSAliasFile : public CSPooled, public CSRefObject {
163
public:
164
	class MSAliasFileShare *ba_share;
165
	bool			ba_isFileInUse;
166
	MSAliasFile		*ba_nextFile;									/* Next file available in the pool */
167
168
	MSAliasFile(MSAliasFileShare *share);
169
	virtual ~MSAliasFile();
170
171
	// Required method for CSPool item.
172
	virtual void returnToPool();
173
174
	
175
	// Required method for item in a CSLinkedList.
176
	virtual CSObject *getNextLink() { return ba_NextLink; }
177
	virtual CSObject *getPrevLink() { return ba_PrevLink; }
178
	virtual void setNextLink(CSObject *link) { ba_NextLink = link; }
179
	virtual void setPrevLink(CSObject *link) { ba_PrevLink = link; }
180
181
	// Index file operations.
182
	MSDiskAliasPtr	findRec(uint32_t hash);
183
	MSDiskAliasPtr	nextRec();
184
	void			addRec(MSDiskAliasPtr rec); 
185
	void			deleteCurrentRec();
186
	void			updateCurrentRec(MSDiskAliasPtr rec);
187
	bool			findRec(MSDiskAliasPtr rec);
188
	
189
	/* When a load is inprogress locks are not required and writes are batched. */
190
	void			startLoad();
191
	void			finishLoad();
192
193
194
private:
195
	bool			nextBucket(bool with_space);
196
		
197
	bool	scanBucket() 
198
			{
199
				while (iCurrentRec) {
200
					iCurrentRec--;
201
					if ( CS_EQ_DISK_4(iDiskHash_4, iBucket[iCurrentRec].ar_hash_4)
202
						&& !CS_IS_NULL_DISK_4(iBucket[iCurrentRec].ar_repo_id_4))
203
						return true;
204
				}
205
				return false;
206
			}
207
			
208
	CSFile				*iFile;			// The index file.
209
	
210
	bool				iLoading;
211
	MSADiskBucketRec	*iBucketCache; // The bucket cache is used during index loading in single thread mode.
212
	MSDiskAliasRec		iBucket[NUM_RECORDS_PER_BUCKET];// The current bucket loaded from disk.
213
	MSABucketLinkedList	*iBucketChain;	// The bucket list for the current hash value.
214
	MSABucketInfo		*iStartBucket;	// The file offset of the bucket the search started at.
215
	MSABucketInfo		*iCurrentBucket;// The currnet bucket, NULL if no bucket is loaded.
216
	
217
	CSDiskValue4		iDiskHash_4;	// The current hash value we are looking for in disk byte order.
218
	uint32_t				iCurrentRec;	// The current record position in the current bucket.
219
	
220
	CSObject			*ba_NextLink;
221
	CSObject			*ba_PrevLink;
222
223
};
224
225
//===========================================
226
class MSAliasFileShare: public CSObject  {
227
public:
228
	MSAliasFileShare(CSPath *path):
229
		msa_filePath(path),
230
		msa_fileSize(0),
231
		msa_pool(NULL),
232
		msa_closing(false)
233
		{
234
			bool isdir = false;
235
			if (path->exists(&isdir))
236
				msa_fileSize = path->getSize();
237
		}
238
		
239
	~MSAliasFileShare()
240
	{
241
		msa_poolFiles.clear();
242
		if (msa_filePath)
243
			msa_filePath->release();
244
			
1548.2.2 by Barry.Leslie at PrimeBase
A lot of minor changes to clean up the code and to get it to build with Drizzle.
245
		for (uint32_t i =0; i < BUCKET_LIST_SIZE; i++)
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
246
			msa_buckets[i].clear();
247
			
248
		msa_empty_buckets.clear();
249
	}
250
	
251
	void close() { msa_poolFiles.clear();}
252
	
253
	MSABucketLinkedList *getBucketChain(uint32_t hash) { return msa_buckets + (hash % BUCKET_LIST_SIZE); }
254
	MSAliasFile		*getPoolFile();
255
	
256
	CSLinkedList	msa_poolFiles;		/* A list of all files in this pool */
257
	uint64_t			msa_fileSize;
258
	CSPath			*msa_filePath;
259
	CSLock			msa_writeLock;	
260
	MSAliasFile		*msa_pool;			/* A list of files currently not in use. */
261
	
262
	CSLock			msa_poolLock;	
263
	bool			msa_closing;
264
	MSABucketLinkedList	msa_empty_buckets;		/* A list of unused buckets. */
265
	
266
	MSABucketLinkedList	msa_buckets[BUCKET_LIST_SIZE];	/* An array of bucket chains. */
267
};
268
269
//===========================================
270
class MSSysMeta : public CSRefObject, public CSPooled {
271
public:
272
	class MSAlias	*md_myMSAlias;
273
	bool			md_isFileInUse;
274
	MSSysMeta		*md_nextFile;									/* Next file available in the pool */
275
276
	MSSysMeta(MSAlias *msa);
277
	virtual ~MSSysMeta();
278
279
	virtual void returnToPool();
280
281
	virtual CSObject *getNextLink() { return md_NextLink; }
282
	virtual CSObject *getPrevLink() { return md_PrevLink; }
283
	virtual void setNextLink(CSObject *link) { md_NextLink = link; }
284
	virtual void setPrevLink(CSObject *link) { md_PrevLink = link; }
285
286
	bool matchAlias(uint32_t repo_id, uint64_t repo_offset, const char *alias);
287
288
private:
289
	MSMetaDataTable	*mtab;
290
	CSObject		*md_NextLink;
291
	CSObject		*md_PrevLink;
292
293
};
294
295
//===========================================
296
class MSAlias  : public CSSharedRefObject  {
297
public:
298
299
	MSAlias(MSDatabase *db_noref);
300
	~MSAlias();
301
302
	void ma_open(const char *file_name = ACTIVE_ALIAS_INDEX);
303
	void ma_close();
304
	void ma_delete() {iDelete = true;}
305
306
	uint32_t addAlias(uint32_t repo_id, uint64_t repo_offset, const char *alias);
307
private:
308
	void addAlias(MSAliasFile *af, MSAliasRec *rec);
309
public:
310
	void deleteAlias(MSDiskAliasPtr diskRec);
311
	void deleteAlias(uint32_t repo_id, uint64_t repo_offset, uint32_t alias_hash);
312
	void resetAlias(uint32_t old_repo_id, uint64_t old_repo_offset, uint32_t alias_hash, uint32_t new_repo_id, uint64_t new_repo_offset);
313
314
	bool findBlobByAlias(const char *alias, bool *referenced, uint32_t *repo_id = NULL, uint64_t *repo_offset = NULL);
315
	bool blobAliasExists(uint32_t repo_id, uint64_t repo_offset, uint32_t alias_hash);
316
private:
317
	bool findBlobByAlias(MSAliasFile *af, const char *alias, bool *referenced, uint32_t *repo_id = NULL, uint64_t *repo_offset = NULL);
318
public:
319
	static uint32_t	hashAlias(const char *ptr);
320
	
321
	void MSAliasBuild();
322
	
323
	friend class MSAliasFile;
324
	friend class MSSysMeta;
325
326
private:
327
	MSDatabase		*iDatabase_br; // This is a back reference so this reference is not counted. 
328
	CSPath			*iFilePath;
329
	
330
	bool			iClosing;
331
	bool			iDelete;			// true when the alias index file should be deleted.
332
	
333
	MSAliasFileShare *iFileShare;	// File information shared between all files in the pool.
334
	
335
	CSLock			iSysTablePoolLock;
336
	MSSysMeta		*iSysTablePool;									/* A list of files currently not in use. */
337
	CSLinkedList	iPoolSysTables;									/* A list of all files in this pool */
338
	
339
	MSAliasFile *getAliasFile() { return iFileShare->getPoolFile();}
340
	void		buildAliasIndex();
341
	void		MSAliasCompress(CSFile *fa, CSSortedList *freeList, MSABucketLinkedList *bucketChain);
342
	void		MSAliasLoad();
343
	bool		hasBlobAlias(uint32_t repo_id, uint64_t repo_offset, const char *alias, bool *referenced);
344
};
345
346
347
#endif //HAVE_ALIAS_SUPPORT
348
349
#endif // __ALIAS_MS_H__