~ubuntu-branches/ubuntu/saucy/drizzle/saucy-proposed

« back to all changes in this revision

Viewing changes to plugin/innobase/fil/fil0fil.c

  • Committer: Bazaar Package Importer
  • Author(s): Monty Taylor
  • Date: 2011-01-04 09:31:58 UTC
  • mfrom: (1.2.5 upstream)
  • Revision ID: james.westby@ubuntu.com-20110104093158-smhgvkfdi2y9au3i
Tags: 2011.01.07-0ubuntu1
New upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*****************************************************************************
2
 
 
3
 
Copyright (C) 1995, 2010, Innobase Oy. All Rights Reserved.
4
 
 
5
 
This program is free software; you can redistribute it and/or modify it under
6
 
the terms of the GNU General Public License as published by the Free Software
7
 
Foundation; version 2 of the License.
8
 
 
9
 
This program is distributed in the hope that it will be useful, but WITHOUT
10
 
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
 
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12
 
 
13
 
You should have received a copy of the GNU General Public License along with
14
 
this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
15
 
St, Fifth Floor, Boston, MA 02110-1301 USA
16
 
 
17
 
*****************************************************************************/
18
 
 
19
 
/**************************************************//**
20
 
@file fil/fil0fil.c
21
 
The tablespace memory cache
22
 
 
23
 
Created 10/25/1995 Heikki Tuuri
24
 
*******************************************************/
25
 
 
26
 
#include "fil0fil.h"
27
 
 
28
 
#include "mem0mem.h"
29
 
#include "hash0hash.h"
30
 
#include "os0file.h"
31
 
#include "mach0data.h"
32
 
#include "buf0buf.h"
33
 
#include "buf0flu.h"
34
 
#include "log0recv.h"
35
 
#include "fsp0fsp.h"
36
 
#include "srv0srv.h"
37
 
#include "srv0start.h"
38
 
#include "mtr0mtr.h"
39
 
#include "mtr0log.h"
40
 
#include "dict0dict.h"
41
 
#include "page0page.h"
42
 
#include "page0zip.h"
43
 
#ifndef UNIV_HOTBACKUP
44
 
# include "buf0lru.h"
45
 
# include "ibuf0ibuf.h"
46
 
# include "sync0sync.h"
47
 
# include "os0sync.h"
48
 
#else /* !UNIV_HOTBACKUP */
49
 
static ulint srv_data_read, srv_data_written;
50
 
#endif /* !UNIV_HOTBACKUP */
51
 
 
52
 
/*
53
 
                IMPLEMENTATION OF THE TABLESPACE MEMORY CACHE
54
 
                =============================================
55
 
 
56
 
The tablespace cache is responsible for providing fast read/write access to
57
 
tablespaces and logs of the database. File creation and deletion is done
58
 
in other modules which know more of the logic of the operation, however.
59
 
 
60
 
A tablespace consists of a chain of files. The size of the files does not
61
 
have to be divisible by the database block size, because we may just leave
62
 
the last incomplete block unused. When a new file is appended to the
63
 
tablespace, the maximum size of the file is also specified. At the moment,
64
 
we think that it is best to extend the file to its maximum size already at
65
 
the creation of the file, because then we can avoid dynamically extending
66
 
the file when more space is needed for the tablespace.
67
 
 
68
 
A block's position in the tablespace is specified with a 32-bit unsigned
69
 
integer. The files in the chain are thought to be catenated, and the block
70
 
corresponding to an address n is the nth block in the catenated file (where
71
 
the first block is named the 0th block, and the incomplete block fragments
72
 
at the end of files are not taken into account). A tablespace can be extended
73
 
by appending a new file at the end of the chain.
74
 
 
75
 
Our tablespace concept is similar to the one of Oracle.
76
 
 
77
 
To acquire more speed in disk transfers, a technique called disk striping is
78
 
sometimes used. This means that logical block addresses are divided in a
79
 
round-robin fashion across several disks. Windows NT supports disk striping,
80
 
so there we do not need to support it in the database. Disk striping is
81
 
implemented in hardware in RAID disks. We conclude that it is not necessary
82
 
to implement it in the database. Oracle 7 does not support disk striping,
83
 
either.
84
 
 
85
 
Another trick used at some database sites is replacing tablespace files by
86
 
raw disks, that is, the whole physical disk drive, or a partition of it, is
87
 
opened as a single file, and it is accessed through byte offsets calculated
88
 
from the start of the disk or the partition. This is recommended in some
89
 
books on database tuning to achieve more speed in i/o. Using raw disk
90
 
certainly prevents the OS from fragmenting disk space, but it is not clear
91
 
if it really adds speed. We measured on the Pentium 100 MHz + NT + NTFS file
92
 
system + EIDE Conner disk only a negligible difference in speed when reading
93
 
from a file, versus reading from a raw disk.
94
 
 
95
 
To have fast access to a tablespace or a log file, we put the data structures
96
 
to a hash table. Each tablespace and log file is given an unique 32-bit
97
 
identifier.
98
 
 
99
 
Some operating systems do not support many open files at the same time,
100
 
though NT seems to tolerate at least 900 open files. Therefore, we put the
101
 
open files in an LRU-list. If we need to open another file, we may close the
102
 
file at the end of the LRU-list. When an i/o-operation is pending on a file,
103
 
the file cannot be closed. We take the file nodes with pending i/o-operations
104
 
out of the LRU-list and keep a count of pending operations. When an operation
105
 
completes, we decrement the count and return the file node to the LRU-list if
106
 
the count drops to zero. */
107
 
 
108
 
/** When mysqld is run, the default directory "." is the mysqld datadir,
109
 
but in the MySQL Embedded Server Library and ibbackup it is not the default
110
 
directory, and we must set the base file path explicitly */
111
 
UNIV_INTERN const char* fil_path_to_mysql_datadir       = ".";
112
 
 
113
 
/** The number of fsyncs done to the log */
114
 
UNIV_INTERN ulint       fil_n_log_flushes                       = 0;
115
 
 
116
 
/** Number of pending redo log flushes */
117
 
UNIV_INTERN ulint       fil_n_pending_log_flushes               = 0;
118
 
/** Number of pending tablespace flushes */
119
 
UNIV_INTERN ulint       fil_n_pending_tablespace_flushes        = 0;
120
 
 
121
 
/** The null file address */
122
 
UNIV_INTERN fil_addr_t  fil_addr_null = {FIL_NULL, 0};
123
 
 
124
 
#ifdef UNIV_PFS_MUTEX
125
 
/* Key to register fil_system_mutex with performance schema */
126
 
UNIV_INTERN mysql_pfs_key_t     fil_system_mutex_key;
127
 
#endif /* UNIV_PFS_MUTEX */
128
 
 
129
 
#ifdef UNIV_PFS_RWLOCK
130
 
/* Key to register file space latch with performance schema */
131
 
UNIV_INTERN mysql_pfs_key_t     fil_space_latch_key;
132
 
#endif /* UNIV_PFS_RWLOCK */
133
 
 
134
 
/** File node of a tablespace or the log data space */
135
 
struct fil_node_struct {
136
 
        fil_space_t*    space;  /*!< backpointer to the space where this node
137
 
                                belongs */
138
 
        char*           name;   /*!< path to the file */
139
 
        ibool           open;   /*!< TRUE if file open */
140
 
        os_file_t       handle; /*!< OS handle to the file, if file open */
141
 
        ibool           is_raw_disk;/*!< TRUE if the 'file' is actually a raw
142
 
                                device or a raw disk partition */
143
 
        ulint           size;   /*!< size of the file in database pages, 0 if
144
 
                                not known yet; the possible last incomplete
145
 
                                megabyte may be ignored if space == 0 */
146
 
        ulint           n_pending;
147
 
                                /*!< count of pending i/o's on this file;
148
 
                                closing of the file is not allowed if
149
 
                                this is > 0 */
150
 
        ulint           n_pending_flushes;
151
 
                                /*!< count of pending flushes on this file;
152
 
                                closing of the file is not allowed if
153
 
                                this is > 0 */
154
 
        ib_int64_t      modification_counter;/*!< when we write to the file we
155
 
                                increment this by one */
156
 
        ib_int64_t      flush_counter;/*!< up to what
157
 
                                modification_counter value we have
158
 
                                flushed the modifications to disk */
159
 
        UT_LIST_NODE_T(fil_node_t) chain;
160
 
                                /*!< link field for the file chain */
161
 
        UT_LIST_NODE_T(fil_node_t) LRU;
162
 
                                /*!< link field for the LRU list */
163
 
        ulint           magic_n;/*!< FIL_NODE_MAGIC_N */
164
 
};
165
 
 
166
 
/** Value of fil_node_struct::magic_n */
167
 
#define FIL_NODE_MAGIC_N        89389
168
 
 
169
 
/** Tablespace or log data space: let us call them by a common name space */
170
 
struct fil_space_struct {
171
 
        char*           name;   /*!< space name = the path to the first file in
172
 
                                it */
173
 
        ulint           id;     /*!< space id */
174
 
        ib_int64_t      tablespace_version;
175
 
                                /*!< in DISCARD/IMPORT this timestamp
176
 
                                is used to check if we should ignore
177
 
                                an insert buffer merge request for a
178
 
                                page because it actually was for the
179
 
                                previous incarnation of the space */
180
 
        ibool           mark;   /*!< this is set to TRUE at database startup if
181
 
                                the space corresponds to a table in the InnoDB
182
 
                                data dictionary; so we can print a warning of
183
 
                                orphaned tablespaces */
184
 
        ibool           stop_ios;/*!< TRUE if we want to rename the
185
 
                                .ibd file of tablespace and want to
186
 
                                stop temporarily posting of new i/o
187
 
                                requests on the file */
188
 
        ibool           stop_ibuf_merges;
189
 
                                /*!< we set this TRUE when we start
190
 
                                deleting a single-table tablespace */
191
 
        ibool           is_being_deleted;
192
 
                                /*!< this is set to TRUE when we start
193
 
                                deleting a single-table tablespace and its
194
 
                                file; when this flag is set no further i/o
195
 
                                or flush requests can be placed on this space,
196
 
                                though there may be such requests still being
197
 
                                processed on this space */
198
 
        ulint           purpose;/*!< FIL_TABLESPACE, FIL_LOG, or
199
 
                                FIL_ARCH_LOG */
200
 
        UT_LIST_BASE_NODE_T(fil_node_t) chain;
201
 
                                /*!< base node for the file chain */
202
 
        ulint           size;   /*!< space size in pages; 0 if a single-table
203
 
                                tablespace whose size we do not know yet;
204
 
                                last incomplete megabytes in data files may be
205
 
                                ignored if space == 0 */
206
 
        ulint           flags;  /*!< compressed page size and file format, or 0 */
207
 
        ulint           n_reserved_extents;
208
 
                                /*!< number of reserved free extents for
209
 
                                ongoing operations like B-tree page split */
210
 
        ulint           n_pending_flushes; /*!< this is positive when flushing
211
 
                                the tablespace to disk; dropping of the
212
 
                                tablespace is forbidden if this is positive */
213
 
        ulint           n_pending_ibuf_merges;/*!< this is positive
214
 
                                when merging insert buffer entries to
215
 
                                a page so that we may need to access
216
 
                                the ibuf bitmap page in the
217
 
                                tablespade: dropping of the tablespace
218
 
                                is forbidden if this is positive */
219
 
        hash_node_t     hash;   /*!< hash chain node */
220
 
        hash_node_t     name_hash;/*!< hash chain the name_hash table */
221
 
#ifndef UNIV_HOTBACKUP
222
 
        rw_lock_t       latch;  /*!< latch protecting the file space storage
223
 
                                allocation */
224
 
#endif /* !UNIV_HOTBACKUP */
225
 
        UT_LIST_NODE_T(fil_space_t) unflushed_spaces;
226
 
                                /*!< list of spaces with at least one unflushed
227
 
                                file we have written to */
228
 
        ibool           is_in_unflushed_spaces; /*!< TRUE if this space is
229
 
                                currently in unflushed_spaces */
230
 
        UT_LIST_NODE_T(fil_space_t) space_list;
231
 
                                /*!< list of all spaces */
232
 
        ulint           magic_n;/*!< FIL_SPACE_MAGIC_N */
233
 
};
234
 
 
235
 
/** Value of fil_space_struct::magic_n */
236
 
#define FIL_SPACE_MAGIC_N       89472
237
 
 
238
 
/** The tablespace memory cache */
239
 
typedef struct fil_system_struct        fil_system_t;
240
 
 
241
 
/** The tablespace memory cache; also the totality of logs (the log
242
 
data space) is stored here; below we talk about tablespaces, but also
243
 
the ib_logfiles form a 'space' and it is handled here */
244
 
 
245
 
struct fil_system_struct {
246
 
#ifndef UNIV_HOTBACKUP
247
 
        mutex_t         mutex;          /*!< The mutex protecting the cache */
248
 
#endif /* !UNIV_HOTBACKUP */
249
 
        hash_table_t*   spaces;         /*!< The hash table of spaces in the
250
 
                                        system; they are hashed on the space
251
 
                                        id */
252
 
        hash_table_t*   name_hash;      /*!< hash table based on the space
253
 
                                        name */
254
 
        UT_LIST_BASE_NODE_T(fil_node_t) LRU;
255
 
                                        /*!< base node for the LRU list of the
256
 
                                        most recently used open files with no
257
 
                                        pending i/o's; if we start an i/o on
258
 
                                        the file, we first remove it from this
259
 
                                        list, and return it to the start of
260
 
                                        the list when the i/o ends;
261
 
                                        log files and the system tablespace are
262
 
                                        not put to this list: they are opened
263
 
                                        after the startup, and kept open until
264
 
                                        shutdown */
265
 
        UT_LIST_BASE_NODE_T(fil_space_t) unflushed_spaces;
266
 
                                        /*!< base node for the list of those
267
 
                                        tablespaces whose files contain
268
 
                                        unflushed writes; those spaces have
269
 
                                        at least one file node where
270
 
                                        modification_counter > flush_counter */
271
 
        ulint           n_open;         /*!< number of files currently open */
272
 
        ulint           max_n_open;     /*!< n_open is not allowed to exceed
273
 
                                        this */
274
 
        ib_int64_t      modification_counter;/*!< when we write to a file we
275
 
                                        increment this by one */
276
 
        ulint           max_assigned_id;/*!< maximum space id in the existing
277
 
                                        tables, or assigned during the time
278
 
                                        mysqld has been up; at an InnoDB
279
 
                                        startup we scan the data dictionary
280
 
                                        and set here the maximum of the
281
 
                                        space id's of the tables there */
282
 
        ib_int64_t      tablespace_version;
283
 
                                        /*!< a counter which is incremented for
284
 
                                        every space object memory creation;
285
 
                                        every space mem object gets a
286
 
                                        'timestamp' from this; in DISCARD/
287
 
                                        IMPORT this is used to check if we
288
 
                                        should ignore an insert buffer merge
289
 
                                        request */
290
 
        UT_LIST_BASE_NODE_T(fil_space_t) space_list;
291
 
                                        /*!< list of all file spaces */
292
 
        ibool           space_id_reuse_warned;
293
 
                                        /* !< TRUE if fil_space_create()
294
 
                                        has issued a warning about
295
 
                                        potential space_id reuse */
296
 
};
297
 
 
298
 
/** The tablespace memory cache. This variable is NULL before the module is
299
 
initialized. */
300
 
static fil_system_t*    fil_system      = NULL;
301
 
 
302
 
 
303
 
/********************************************************************//**
304
 
NOTE: you must call fil_mutex_enter_and_prepare_for_io() first!
305
 
 
306
 
Prepares a file node for i/o. Opens the file if it is closed. Updates the
307
 
pending i/o's field in the node and the system appropriately. Takes the node
308
 
off the LRU list if it is in the LRU list. The caller must hold the fil_sys
309
 
mutex. */
310
 
static
311
 
void
312
 
fil_node_prepare_for_io(
313
 
/*====================*/
314
 
        fil_node_t*     node,   /*!< in: file node */
315
 
        fil_system_t*   system, /*!< in: tablespace memory cache */
316
 
        fil_space_t*    space); /*!< in: space */
317
 
/********************************************************************//**
318
 
Updates the data structures when an i/o operation finishes. Updates the
319
 
pending i/o's field in the node appropriately. */
320
 
static
321
 
void
322
 
fil_node_complete_io(
323
 
/*=================*/
324
 
        fil_node_t*     node,   /*!< in: file node */
325
 
        fil_system_t*   system, /*!< in: tablespace memory cache */
326
 
        ulint           type);  /*!< in: OS_FILE_WRITE or OS_FILE_READ; marks
327
 
                                the node as modified if
328
 
                                type == OS_FILE_WRITE */
329
 
/*******************************************************************//**
330
 
Checks if a single-table tablespace for a given table name exists in the
331
 
tablespace memory cache.
332
 
@return space id, ULINT_UNDEFINED if not found */
333
 
static
334
 
ulint
335
 
fil_get_space_id_for_table(
336
 
/*=======================*/
337
 
        const char*     name);  /*!< in: table name in the standard
338
 
                                'databasename/tablename' format */
339
 
/*******************************************************************//**
340
 
Frees a space object from the tablespace memory cache. Closes the files in
341
 
the chain but does not delete them. There must not be any pending i/o's or
342
 
flushes on the files. */
343
 
static
344
 
ibool
345
 
fil_space_free(
346
 
/*===========*/
347
 
                                /* out: TRUE if success */
348
 
        ulint           id,     /* in: space id */
349
 
        ibool           own_mutex);/* in: TRUE if own system->mutex */
350
 
/********************************************************************//**
351
 
Reads data from a space to a buffer. Remember that the possible incomplete
352
 
blocks at the end of file are ignored: they are not taken into account when
353
 
calculating the byte offset within a space.
354
 
@return DB_SUCCESS, or DB_TABLESPACE_DELETED if we are trying to do
355
 
i/o on a tablespace which does not exist */
356
 
UNIV_INLINE
357
 
ulint
358
 
fil_read(
359
 
/*=====*/
360
 
        ibool   sync,           /*!< in: TRUE if synchronous aio is desired */
361
 
        ulint   space_id,       /*!< in: space id */
362
 
        ulint   zip_size,       /*!< in: compressed page size in bytes;
363
 
                                0 for uncompressed pages */
364
 
        ulint   block_offset,   /*!< in: offset in number of blocks */
365
 
        ulint   byte_offset,    /*!< in: remainder of offset in bytes; in aio
366
 
                                this must be divisible by the OS block size */
367
 
        ulint   len,            /*!< in: how many bytes to read; this must not
368
 
                                cross a file boundary; in aio this must be a
369
 
                                block size multiple */
370
 
        void*   buf,            /*!< in/out: buffer where to store data read;
371
 
                                in aio this must be appropriately aligned */
372
 
        void*   message)        /*!< in: message for aio handler if non-sync
373
 
                                aio used, else ignored */
374
 
{
375
 
        return(fil_io(OS_FILE_READ, sync, space_id, zip_size, block_offset,
376
 
                                          byte_offset, len, buf, message));
377
 
}
378
 
 
379
 
/********************************************************************//**
380
 
Writes data to a space from a buffer. Remember that the possible incomplete
381
 
blocks at the end of file are ignored: they are not taken into account when
382
 
calculating the byte offset within a space.
383
 
@return DB_SUCCESS, or DB_TABLESPACE_DELETED if we are trying to do
384
 
i/o on a tablespace which does not exist */
385
 
UNIV_INLINE
386
 
ulint
387
 
fil_write(
388
 
/*======*/
389
 
        ibool   sync,           /*!< in: TRUE if synchronous aio is desired */
390
 
        ulint   space_id,       /*!< in: space id */
391
 
        ulint   zip_size,       /*!< in: compressed page size in bytes;
392
 
                                0 for uncompressed pages */
393
 
        ulint   block_offset,   /*!< in: offset in number of blocks */
394
 
        ulint   byte_offset,    /*!< in: remainder of offset in bytes; in aio
395
 
                                this must be divisible by the OS block size */
396
 
        ulint   len,            /*!< in: how many bytes to write; this must
397
 
                                not cross a file boundary; in aio this must
398
 
                                be a block size multiple */
399
 
        void*   buf,            /*!< in: buffer from which to write; in aio
400
 
                                this must be appropriately aligned */
401
 
        void*   message)        /*!< in: message for aio handler if non-sync
402
 
                                aio used, else ignored */
403
 
{
404
 
        return(fil_io(OS_FILE_WRITE, sync, space_id, zip_size, block_offset,
405
 
                                           byte_offset, len, buf, message));
406
 
}
407
 
 
408
 
/*******************************************************************//**
409
 
Returns the table space by a given id, NULL if not found. */
410
 
UNIV_INLINE
411
 
fil_space_t*
412
 
fil_space_get_by_id(
413
 
/*================*/
414
 
        ulint   id)     /*!< in: space id */
415
 
{
416
 
        fil_space_t*    space;
417
 
 
418
 
        ut_ad(mutex_own(&fil_system->mutex));
419
 
 
420
 
        HASH_SEARCH(hash, fil_system->spaces, id,
421
 
                    fil_space_t*, space,
422
 
                    ut_ad(space->magic_n == FIL_SPACE_MAGIC_N),
423
 
                    space->id == id);
424
 
 
425
 
        return(space);
426
 
}
427
 
 
428
 
/*******************************************************************//**
429
 
Returns the table space by a given name, NULL if not found. */
430
 
UNIV_INLINE
431
 
fil_space_t*
432
 
fil_space_get_by_name(
433
 
/*==================*/
434
 
        const char*     name)   /*!< in: space name */
435
 
{
436
 
        fil_space_t*    space;
437
 
        ulint           fold;
438
 
 
439
 
        ut_ad(mutex_own(&fil_system->mutex));
440
 
 
441
 
        fold = ut_fold_string(name);
442
 
 
443
 
        HASH_SEARCH(name_hash, fil_system->name_hash, fold,
444
 
                    fil_space_t*, space,
445
 
                    ut_ad(space->magic_n == FIL_SPACE_MAGIC_N),
446
 
                    !strcmp(name, space->name));
447
 
 
448
 
        return(space);
449
 
}
450
 
 
451
 
#ifndef UNIV_HOTBACKUP
452
 
/*******************************************************************//**
453
 
Returns the version number of a tablespace, -1 if not found.
454
 
@return version number, -1 if the tablespace does not exist in the
455
 
memory cache */
456
 
UNIV_INTERN
457
 
ib_int64_t
458
 
fil_space_get_version(
459
 
/*==================*/
460
 
        ulint   id)     /*!< in: space id */
461
 
{
462
 
        fil_space_t*    space;
463
 
        ib_int64_t      version         = -1;
464
 
 
465
 
        ut_ad(fil_system);
466
 
 
467
 
        mutex_enter(&fil_system->mutex);
468
 
 
469
 
        space = fil_space_get_by_id(id);
470
 
 
471
 
        if (space) {
472
 
                version = space->tablespace_version;
473
 
        }
474
 
 
475
 
        mutex_exit(&fil_system->mutex);
476
 
 
477
 
        return(version);
478
 
}
479
 
 
480
 
/*******************************************************************//**
481
 
Returns the latch of a file space.
482
 
@return latch protecting storage allocation */
483
 
UNIV_INTERN
484
 
rw_lock_t*
485
 
fil_space_get_latch(
486
 
/*================*/
487
 
        ulint   id,     /*!< in: space id */
488
 
        ulint*  flags)  /*!< out: tablespace flags */
489
 
{
490
 
        fil_space_t*    space;
491
 
 
492
 
        ut_ad(fil_system);
493
 
 
494
 
        mutex_enter(&fil_system->mutex);
495
 
 
496
 
        space = fil_space_get_by_id(id);
497
 
 
498
 
        ut_a(space);
499
 
 
500
 
        if (flags) {
501
 
                *flags = space->flags;
502
 
        }
503
 
 
504
 
        mutex_exit(&fil_system->mutex);
505
 
 
506
 
        return(&(space->latch));
507
 
}
508
 
 
509
 
/*******************************************************************//**
510
 
Returns the type of a file space.
511
 
@return FIL_TABLESPACE or FIL_LOG */
512
 
UNIV_INTERN
513
 
ulint
514
 
fil_space_get_type(
515
 
/*===============*/
516
 
        ulint   id)     /*!< in: space id */
517
 
{
518
 
        fil_space_t*    space;
519
 
 
520
 
        ut_ad(fil_system);
521
 
 
522
 
        mutex_enter(&fil_system->mutex);
523
 
 
524
 
        space = fil_space_get_by_id(id);
525
 
 
526
 
        ut_a(space);
527
 
 
528
 
        mutex_exit(&fil_system->mutex);
529
 
 
530
 
        return(space->purpose);
531
 
}
532
 
#endif /* !UNIV_HOTBACKUP */
533
 
 
534
 
/**********************************************************************//**
535
 
Checks if all the file nodes in a space are flushed. The caller must hold
536
 
the fil_system mutex.
537
 
@return TRUE if all are flushed */
538
 
static
539
 
ibool
540
 
fil_space_is_flushed(
541
 
/*=================*/
542
 
        fil_space_t*    space)  /*!< in: space */
543
 
{
544
 
        fil_node_t*     node;
545
 
 
546
 
        ut_ad(mutex_own(&fil_system->mutex));
547
 
 
548
 
        node = UT_LIST_GET_FIRST(space->chain);
549
 
 
550
 
        while (node) {
551
 
                if (node->modification_counter > node->flush_counter) {
552
 
 
553
 
                        return(FALSE);
554
 
                }
555
 
 
556
 
                node = UT_LIST_GET_NEXT(chain, node);
557
 
        }
558
 
 
559
 
        return(TRUE);
560
 
}
561
 
 
562
 
/*******************************************************************//**
563
 
Appends a new file to the chain of files of a space. File must be closed. */
564
 
UNIV_INTERN
565
 
void
566
 
fil_node_create(
567
 
/*============*/
568
 
        const char*     name,   /*!< in: file name (file must be closed) */
569
 
        ulint           size,   /*!< in: file size in database blocks, rounded
570
 
                                downwards to an integer */
571
 
        ulint           id,     /*!< in: space id where to append */
572
 
        ibool           is_raw) /*!< in: TRUE if a raw device or
573
 
                                a raw disk partition */
574
 
{
575
 
        fil_node_t*     node;
576
 
        fil_space_t*    space;
577
 
 
578
 
        ut_a(fil_system);
579
 
        ut_a(name);
580
 
 
581
 
        mutex_enter(&fil_system->mutex);
582
 
 
583
 
        node = mem_alloc(sizeof(fil_node_t));
584
 
 
585
 
        node->name = mem_strdup(name);
586
 
        node->open = FALSE;
587
 
 
588
 
        ut_a(!is_raw || srv_start_raw_disk_in_use);
589
 
 
590
 
        node->is_raw_disk = is_raw;
591
 
        node->size = size;
592
 
        node->magic_n = FIL_NODE_MAGIC_N;
593
 
        node->n_pending = 0;
594
 
        node->n_pending_flushes = 0;
595
 
 
596
 
        node->modification_counter = 0;
597
 
        node->flush_counter = 0;
598
 
 
599
 
        space = fil_space_get_by_id(id);
600
 
 
601
 
        if (!space) {
602
 
                ut_print_timestamp(stderr);
603
 
                fprintf(stderr,
604
 
                        "  InnoDB: Error: Could not find tablespace %lu for\n"
605
 
                        "InnoDB: file ", (ulong) id);
606
 
                ut_print_filename(stderr, name);
607
 
                fputs(" in the tablespace memory cache.\n", stderr);
608
 
                mem_free(node->name);
609
 
 
610
 
                mem_free(node);
611
 
 
612
 
                mutex_exit(&fil_system->mutex);
613
 
 
614
 
                return;
615
 
        }
616
 
 
617
 
        space->size += size;
618
 
 
619
 
        node->space = space;
620
 
 
621
 
        UT_LIST_ADD_LAST(chain, space->chain, node);
622
 
 
623
 
        if (id < SRV_LOG_SPACE_FIRST_ID && fil_system->max_assigned_id < id) {
624
 
 
625
 
                fil_system->max_assigned_id = id;
626
 
        }
627
 
 
628
 
        mutex_exit(&fil_system->mutex);
629
 
}
630
 
 
631
 
/********************************************************************//**
632
 
Opens a the file of a node of a tablespace. The caller must own the fil_system
633
 
mutex. */
634
 
static
635
 
void
636
 
fil_node_open_file(
637
 
/*===============*/
638
 
        fil_node_t*     node,   /*!< in: file node */
639
 
        fil_system_t*   system, /*!< in: tablespace memory cache */
640
 
        fil_space_t*    space)  /*!< in: space */
641
 
{
642
 
        ib_int64_t      size_bytes;
643
 
        ulint           size_low;
644
 
        ulint           size_high;
645
 
        ibool           ret;
646
 
        ibool           success;
647
 
        byte*           buf2;
648
 
        byte*           page;
649
 
        ulint           space_id;
650
 
        ulint           flags;
651
 
 
652
 
        ut_ad(mutex_own(&(system->mutex)));
653
 
        ut_a(node->n_pending == 0);
654
 
        ut_a(node->open == FALSE);
655
 
 
656
 
        if (node->size == 0) {
657
 
                /* It must be a single-table tablespace and we do not know the
658
 
                size of the file yet. First we open the file in the normal
659
 
                mode, no async I/O here, for simplicity. Then do some checks,
660
 
                and close the file again.
661
 
                NOTE that we could not use the simple file read function
662
 
                os_file_read() in Windows to read from a file opened for
663
 
                async I/O! */
664
 
 
665
 
                node->handle = os_file_create_simple_no_error_handling(
666
 
                        innodb_file_data_key, node->name, OS_FILE_OPEN,
667
 
                        OS_FILE_READ_ONLY, &success);
668
 
                if (!success) {
669
 
                        /* The following call prints an error message */
670
 
                        os_file_get_last_error(TRUE);
671
 
 
672
 
                        ut_print_timestamp(stderr);
673
 
 
674
 
                        fprintf(stderr,
675
 
                                "  InnoDB: Fatal error: cannot open %s\n."
676
 
                                "InnoDB: Have you deleted .ibd files"
677
 
                                " under a running mysqld server?\n",
678
 
                                node->name);
679
 
                        ut_a(0);
680
 
                }
681
 
 
682
 
                os_file_get_size(node->handle, &size_low, &size_high);
683
 
 
684
 
                size_bytes = (((ib_int64_t)size_high) << 32)
685
 
                        + (ib_int64_t)size_low;
686
 
#ifdef UNIV_HOTBACKUP
687
 
                if (space->id == 0) {
688
 
                        node->size = (ulint) (size_bytes / UNIV_PAGE_SIZE);
689
 
                        os_file_close(node->handle);
690
 
                        goto add_size;
691
 
                }
692
 
#endif /* UNIV_HOTBACKUP */
693
 
                ut_a(space->purpose != FIL_LOG);
694
 
                ut_a(space->id != 0);
695
 
 
696
 
                if (size_bytes < FIL_IBD_FILE_INITIAL_SIZE * UNIV_PAGE_SIZE) {
697
 
                        fprintf(stderr,
698
 
                                "InnoDB: Error: the size of single-table"
699
 
                                " tablespace file %s\n"
700
 
                                "InnoDB: is only %lu %lu,"
701
 
                                " should be at least %lu!\n",
702
 
                                node->name,
703
 
                                (ulong) size_high,
704
 
                                (ulong) size_low,
705
 
                                (ulong) (FIL_IBD_FILE_INITIAL_SIZE
706
 
                                         * UNIV_PAGE_SIZE));
707
 
 
708
 
                        ut_a(0);
709
 
                }
710
 
 
711
 
                /* Read the first page of the tablespace */
712
 
 
713
 
                buf2 = ut_malloc(2 * UNIV_PAGE_SIZE);
714
 
                /* Align the memory for file i/o if we might have O_DIRECT
715
 
                set */
716
 
                page = ut_align(buf2, UNIV_PAGE_SIZE);
717
 
 
718
 
                success = os_file_read(node->handle, page, 0, 0,
719
 
                                       UNIV_PAGE_SIZE);
720
 
                space_id = fsp_header_get_space_id(page);
721
 
                flags = fsp_header_get_flags(page);
722
 
 
723
 
                ut_free(buf2);
724
 
 
725
 
                /* Close the file now that we have read the space id from it */
726
 
 
727
 
                os_file_close(node->handle);
728
 
 
729
 
                if (UNIV_UNLIKELY(space_id != space->id)) {
730
 
                        fprintf(stderr,
731
 
                                "InnoDB: Error: tablespace id is %lu"
732
 
                                " in the data dictionary\n"
733
 
                                "InnoDB: but in file %s it is %lu!\n",
734
 
                                space->id, node->name, space_id);
735
 
 
736
 
                        ut_error;
737
 
                }
738
 
 
739
 
                if (UNIV_UNLIKELY(space_id == ULINT_UNDEFINED
740
 
                                  || space_id == 0)) {
741
 
                        fprintf(stderr,
742
 
                                "InnoDB: Error: tablespace id %lu"
743
 
                                " in file %s is not sensible\n",
744
 
                                (ulong) space_id, node->name);
745
 
 
746
 
                        ut_error;
747
 
                }
748
 
 
749
 
                if (UNIV_UNLIKELY(space->flags != flags)) {
750
 
                        fprintf(stderr,
751
 
                                "InnoDB: Error: table flags are %lx"
752
 
                                " in the data dictionary\n"
753
 
                                "InnoDB: but the flags in file %s are %lx!\n",
754
 
                                space->flags, node->name, flags);
755
 
 
756
 
                        ut_error;
757
 
                }
758
 
 
759
 
                if (size_bytes >= 1024 * 1024) {
760
 
                        /* Truncate the size to whole megabytes. */
761
 
                        size_bytes = ut_2pow_round(size_bytes, 1024 * 1024);
762
 
                }
763
 
 
764
 
                if (!(flags & DICT_TF_ZSSIZE_MASK)) {
765
 
                        node->size = (ulint) (size_bytes / UNIV_PAGE_SIZE);
766
 
                } else {
767
 
                        node->size = (ulint)
768
 
                                (size_bytes
769
 
                                 / dict_table_flags_to_zip_size(flags));
770
 
                }
771
 
 
772
 
#ifdef UNIV_HOTBACKUP
773
 
add_size:
774
 
#endif /* UNIV_HOTBACKUP */
775
 
                space->size += node->size;
776
 
        }
777
 
 
778
 
        /* printf("Opening file %s\n", node->name); */
779
 
 
780
 
        /* Open the file for reading and writing, in Windows normally in the
781
 
        unbuffered async I/O mode, though global variables may make
782
 
        os_file_create() to fall back to the normal file I/O mode. */
783
 
 
784
 
        if (space->purpose == FIL_LOG) {
785
 
                node->handle = os_file_create(innodb_file_log_key,
786
 
                                              node->name, OS_FILE_OPEN,
787
 
                                              OS_FILE_AIO, OS_LOG_FILE,
788
 
                                              &ret);
789
 
        } else if (node->is_raw_disk) {
790
 
                node->handle = os_file_create(innodb_file_data_key,
791
 
                                              node->name,
792
 
                                              OS_FILE_OPEN_RAW,
793
 
                                              OS_FILE_AIO, OS_DATA_FILE,
794
 
                                                     &ret);
795
 
        } else {
796
 
                node->handle = os_file_create(innodb_file_data_key,
797
 
                                              node->name, OS_FILE_OPEN,
798
 
                                              OS_FILE_AIO, OS_DATA_FILE,
799
 
                                              &ret);
800
 
        }
801
 
 
802
 
        ut_a(ret);
803
 
 
804
 
        node->open = TRUE;
805
 
 
806
 
        system->n_open++;
807
 
 
808
 
        if (space->purpose == FIL_TABLESPACE && space->id != 0) {
809
 
                /* Put the node to the LRU list */
810
 
                UT_LIST_ADD_FIRST(LRU, system->LRU, node);
811
 
        }
812
 
}
813
 
 
814
 
/**********************************************************************//**
815
 
Closes a file. */
816
 
static
817
 
void
818
 
fil_node_close_file(
819
 
/*================*/
820
 
        fil_node_t*     node,   /*!< in: file node */
821
 
        fil_system_t*   system) /*!< in: tablespace memory cache */
822
 
{
823
 
        ibool   ret;
824
 
 
825
 
        ut_ad(node && system);
826
 
        ut_ad(mutex_own(&(system->mutex)));
827
 
        ut_a(node->open);
828
 
        ut_a(node->n_pending == 0);
829
 
        ut_a(node->n_pending_flushes == 0);
830
 
        ut_a(node->modification_counter == node->flush_counter);
831
 
 
832
 
        ret = os_file_close(node->handle);
833
 
        ut_a(ret);
834
 
 
835
 
        /* printf("Closing file %s\n", node->name); */
836
 
 
837
 
        node->open = FALSE;
838
 
        ut_a(system->n_open > 0);
839
 
        system->n_open--;
840
 
 
841
 
        if (node->space->purpose == FIL_TABLESPACE && node->space->id != 0) {
842
 
                ut_a(UT_LIST_GET_LEN(system->LRU) > 0);
843
 
 
844
 
                /* The node is in the LRU list, remove it */
845
 
                UT_LIST_REMOVE(LRU, system->LRU, node);
846
 
        }
847
 
}
848
 
 
849
 
/********************************************************************//**
850
 
Tries to close a file in the LRU list. The caller must hold the fil_sys
851
 
mutex.
852
 
@return TRUE if success, FALSE if should retry later; since i/o's
853
 
generally complete in < 100 ms, and as InnoDB writes at most 128 pages
854
 
from the buffer pool in a batch, and then immediately flushes the
855
 
files, there is a good chance that the next time we find a suitable
856
 
node from the LRU list */
857
 
static
858
 
ibool
859
 
fil_try_to_close_file_in_LRU(
860
 
/*=========================*/
861
 
        ibool   print_info)     /*!< in: if TRUE, prints information why it
862
 
                                cannot close a file */
863
 
{
864
 
        fil_node_t*     node;
865
 
 
866
 
        ut_ad(mutex_own(&fil_system->mutex));
867
 
 
868
 
        node = UT_LIST_GET_LAST(fil_system->LRU);
869
 
 
870
 
        if (print_info) {
871
 
                fprintf(stderr,
872
 
                        "InnoDB: fil_sys open file LRU len %lu\n",
873
 
                        (ulong) UT_LIST_GET_LEN(fil_system->LRU));
874
 
        }
875
 
 
876
 
        while (node != NULL) {
877
 
                if (node->modification_counter == node->flush_counter
878
 
                    && node->n_pending_flushes == 0) {
879
 
 
880
 
                        fil_node_close_file(node, fil_system);
881
 
 
882
 
                        return(TRUE);
883
 
                }
884
 
 
885
 
                if (print_info && node->n_pending_flushes > 0) {
886
 
                        fputs("InnoDB: cannot close file ", stderr);
887
 
                        ut_print_filename(stderr, node->name);
888
 
                        fprintf(stderr, ", because n_pending_flushes %lu\n",
889
 
                                (ulong) node->n_pending_flushes);
890
 
                }
891
 
 
892
 
                if (print_info
893
 
                    && node->modification_counter != node->flush_counter) {
894
 
                        fputs("InnoDB: cannot close file ", stderr);
895
 
                        ut_print_filename(stderr, node->name);
896
 
                        fprintf(stderr,
897
 
                                ", because mod_count %ld != fl_count %ld\n",
898
 
                                (long) node->modification_counter,
899
 
                                (long) node->flush_counter);
900
 
                }
901
 
 
902
 
                node = UT_LIST_GET_PREV(LRU, node);
903
 
        }
904
 
 
905
 
        return(FALSE);
906
 
}
907
 
 
908
 
/*******************************************************************//**
909
 
Reserves the fil_system mutex and tries to make sure we can open at least one
910
 
file while holding it. This should be called before calling
911
 
fil_node_prepare_for_io(), because that function may need to open a file. */
912
 
static
913
 
void
914
 
fil_mutex_enter_and_prepare_for_io(
915
 
/*===============================*/
916
 
        ulint   space_id)       /*!< in: space id */
917
 
{
918
 
        fil_space_t*    space;
919
 
        ibool           success;
920
 
        ibool           print_info      = FALSE;
921
 
        ulint           count           = 0;
922
 
        ulint           count2          = 0;
923
 
 
924
 
retry:
925
 
        mutex_enter(&fil_system->mutex);
926
 
 
927
 
        if (space_id == 0 || space_id >= SRV_LOG_SPACE_FIRST_ID) {
928
 
                /* We keep log files and system tablespace files always open;
929
 
                this is important in preventing deadlocks in this module, as
930
 
                a page read completion often performs another read from the
931
 
                insert buffer. The insert buffer is in tablespace 0, and we
932
 
                cannot end up waiting in this function. */
933
 
 
934
 
                return;
935
 
        }
936
 
 
937
 
        if (fil_system->n_open < fil_system->max_n_open) {
938
 
 
939
 
                return;
940
 
        }
941
 
 
942
 
        space = fil_space_get_by_id(space_id);
943
 
 
944
 
        if (space != NULL && space->stop_ios) {
945
 
                /* We are going to do a rename file and want to stop new i/o's
946
 
                for a while */
947
 
 
948
 
                if (count2 > 20000) {
949
 
                        fputs("InnoDB: Warning: tablespace ", stderr);
950
 
                        ut_print_filename(stderr, space->name);
951
 
                        fprintf(stderr,
952
 
                                " has i/o ops stopped for a long time %lu\n",
953
 
                                (ulong) count2);
954
 
                }
955
 
 
956
 
                mutex_exit(&fil_system->mutex);
957
 
 
958
 
                os_thread_sleep(20000);
959
 
 
960
 
                count2++;
961
 
 
962
 
                goto retry;
963
 
        }
964
 
 
965
 
        /* If the file is already open, no need to do anything; if the space
966
 
        does not exist, we handle the situation in the function which called
967
 
        this function */
968
 
 
969
 
        if (!space || UT_LIST_GET_FIRST(space->chain)->open) {
970
 
 
971
 
                return;
972
 
        }
973
 
 
974
 
        if (count > 1) {
975
 
                print_info = TRUE;
976
 
        }
977
 
 
978
 
        /* Too many files are open, try to close some */
979
 
close_more:
980
 
        success = fil_try_to_close_file_in_LRU(print_info);
981
 
 
982
 
        if (success && fil_system->n_open >= fil_system->max_n_open) {
983
 
 
984
 
                goto close_more;
985
 
        }
986
 
 
987
 
        if (fil_system->n_open < fil_system->max_n_open) {
988
 
                /* Ok */
989
 
 
990
 
                return;
991
 
        }
992
 
 
993
 
        if (count >= 2) {
994
 
                ut_print_timestamp(stderr);
995
 
                fprintf(stderr,
996
 
                        "  InnoDB: Warning: too many (%lu) files stay open"
997
 
                        " while the maximum\n"
998
 
                        "InnoDB: allowed value would be %lu.\n"
999
 
                        "InnoDB: You may need to raise the value of"
1000
 
                        " innodb_open_files in\n"
1001
 
                        "InnoDB: my.cnf.\n",
1002
 
                        (ulong) fil_system->n_open,
1003
 
                        (ulong) fil_system->max_n_open);
1004
 
 
1005
 
                return;
1006
 
        }
1007
 
 
1008
 
        mutex_exit(&fil_system->mutex);
1009
 
 
1010
 
#ifndef UNIV_HOTBACKUP
1011
 
        /* Wake the i/o-handler threads to make sure pending i/o's are
1012
 
        performed */
1013
 
        os_aio_simulated_wake_handler_threads();
1014
 
 
1015
 
        os_thread_sleep(20000);
1016
 
#endif
1017
 
        /* Flush tablespaces so that we can close modified files in the LRU
1018
 
        list */
1019
 
 
1020
 
        fil_flush_file_spaces(FIL_TABLESPACE);
1021
 
 
1022
 
        count++;
1023
 
 
1024
 
        goto retry;
1025
 
}
1026
 
 
1027
 
/*******************************************************************//**
1028
 
Frees a file node object from a tablespace memory cache. */
1029
 
static
1030
 
void
1031
 
fil_node_free(
1032
 
/*==========*/
1033
 
        fil_node_t*     node,   /*!< in, own: file node */
1034
 
        fil_system_t*   system, /*!< in: tablespace memory cache */
1035
 
        fil_space_t*    space)  /*!< in: space where the file node is chained */
1036
 
{
1037
 
        ut_ad(node && system && space);
1038
 
        ut_ad(mutex_own(&(system->mutex)));
1039
 
        ut_a(node->magic_n == FIL_NODE_MAGIC_N);
1040
 
        ut_a(node->n_pending == 0);
1041
 
 
1042
 
        if (node->open) {
1043
 
                /* We fool the assertion in fil_node_close_file() to think
1044
 
                there are no unflushed modifications in the file */
1045
 
 
1046
 
                node->modification_counter = node->flush_counter;
1047
 
 
1048
 
                if (space->is_in_unflushed_spaces
1049
 
                    && fil_space_is_flushed(space)) {
1050
 
 
1051
 
                        space->is_in_unflushed_spaces = FALSE;
1052
 
 
1053
 
                        UT_LIST_REMOVE(unflushed_spaces,
1054
 
                                       system->unflushed_spaces,
1055
 
                                       space);
1056
 
                }
1057
 
 
1058
 
                fil_node_close_file(node, system);
1059
 
        }
1060
 
 
1061
 
        space->size -= node->size;
1062
 
 
1063
 
        UT_LIST_REMOVE(chain, space->chain, node);
1064
 
 
1065
 
        mem_free(node->name);
1066
 
        mem_free(node);
1067
 
}
1068
 
 
1069
 
#ifdef UNIV_LOG_ARCHIVE
1070
 
/****************************************************************//**
1071
 
Drops files from the start of a file space, so that its size is cut by
1072
 
the amount given. */
1073
 
UNIV_INTERN
1074
 
void
1075
 
fil_space_truncate_start(
1076
 
/*=====================*/
1077
 
        ulint   id,             /*!< in: space id */
1078
 
        ulint   trunc_len)      /*!< in: truncate by this much; it is an error
1079
 
                                if this does not equal to the combined size of
1080
 
                                some initial files in the space */
1081
 
{
1082
 
        fil_node_t*     node;
1083
 
        fil_space_t*    space;
1084
 
 
1085
 
        mutex_enter(&fil_system->mutex);
1086
 
 
1087
 
        space = fil_space_get_by_id(id);
1088
 
 
1089
 
        ut_a(space);
1090
 
 
1091
 
        while (trunc_len > 0) {
1092
 
                node = UT_LIST_GET_FIRST(space->chain);
1093
 
 
1094
 
                ut_a(node->size * UNIV_PAGE_SIZE <= trunc_len);
1095
 
 
1096
 
                trunc_len -= node->size * UNIV_PAGE_SIZE;
1097
 
 
1098
 
                fil_node_free(node, fil_system, space);
1099
 
        }
1100
 
 
1101
 
        mutex_exit(&fil_system->mutex);
1102
 
}
1103
 
#endif /* UNIV_LOG_ARCHIVE */
1104
 
 
1105
 
/*******************************************************************//**
1106
 
Creates a space memory object and puts it to the tablespace memory cache. If
1107
 
there is an error, prints an error message to the .err log.
1108
 
@return TRUE if success */
1109
 
UNIV_INTERN
1110
 
ibool
1111
 
fil_space_create(
1112
 
/*=============*/
1113
 
        const char*     name,   /*!< in: space name */
1114
 
        ulint           id,     /*!< in: space id */
1115
 
        ulint           flags,  /*!< in: compressed page size
1116
 
                                and file format, or 0 */
1117
 
        ulint           purpose)/*!< in: FIL_TABLESPACE, or FIL_LOG if log */
1118
 
{
1119
 
        fil_space_t*    space;
1120
 
 
1121
 
        /* The tablespace flags (FSP_SPACE_FLAGS) should be 0 for
1122
 
        ROW_FORMAT=COMPACT
1123
 
        ((table->flags & ~(~0 << DICT_TF_BITS)) == DICT_TF_COMPACT) and
1124
 
        ROW_FORMAT=REDUNDANT (table->flags == 0).  For any other
1125
 
        format, the tablespace flags should equal
1126
 
        (table->flags & ~(~0 << DICT_TF_BITS)). */
1127
 
        ut_a(flags != DICT_TF_COMPACT);
1128
 
        ut_a(!(flags & (~0UL << DICT_TF_BITS)));
1129
 
 
1130
 
try_again:
1131
 
        /*printf(
1132
 
        "InnoDB: Adding tablespace %lu of name %s, purpose %lu\n", id, name,
1133
 
        purpose);*/
1134
 
 
1135
 
        ut_a(fil_system);
1136
 
        ut_a(name);
1137
 
 
1138
 
        mutex_enter(&fil_system->mutex);
1139
 
 
1140
 
        space = fil_space_get_by_name(name);
1141
 
 
1142
 
        if (UNIV_LIKELY_NULL(space)) {
1143
 
                ulint   namesake_id;
1144
 
 
1145
 
                ut_print_timestamp(stderr);
1146
 
                fprintf(stderr,
1147
 
                        "  InnoDB: Warning: trying to init to the"
1148
 
                        " tablespace memory cache\n"
1149
 
                        "InnoDB: a tablespace %lu of name ", (ulong) id);
1150
 
                ut_print_filename(stderr, name);
1151
 
                fprintf(stderr, ",\n"
1152
 
                        "InnoDB: but a tablespace %lu of the same name\n"
1153
 
                        "InnoDB: already exists in the"
1154
 
                        " tablespace memory cache!\n",
1155
 
                        (ulong) space->id);
1156
 
 
1157
 
                if (id == 0 || purpose != FIL_TABLESPACE) {
1158
 
 
1159
 
                        mutex_exit(&fil_system->mutex);
1160
 
 
1161
 
                        return(FALSE);
1162
 
                }
1163
 
 
1164
 
                fprintf(stderr,
1165
 
                        "InnoDB: We assume that InnoDB did a crash recovery,"
1166
 
                        " and you had\n"
1167
 
                        "InnoDB: an .ibd file for which the table"
1168
 
                        " did not exist in the\n"
1169
 
                        "InnoDB: InnoDB internal data dictionary in the"
1170
 
                        " ibdata files.\n"
1171
 
                        "InnoDB: We assume that you later removed the"
1172
 
                        " .ibd and .frm files,\n"
1173
 
                        "InnoDB: and are now trying to recreate the table."
1174
 
                        " We now remove the\n"
1175
 
                        "InnoDB: conflicting tablespace object"
1176
 
                        " from the memory cache and try\n"
1177
 
                        "InnoDB: the init again.\n");
1178
 
 
1179
 
                namesake_id = space->id;
1180
 
 
1181
 
                mutex_exit(&fil_system->mutex);
1182
 
 
1183
 
                fil_space_free(namesake_id, FALSE);
1184
 
 
1185
 
                goto try_again;
1186
 
        }
1187
 
 
1188
 
        space = fil_space_get_by_id(id);
1189
 
 
1190
 
        if (UNIV_LIKELY_NULL(space)) {
1191
 
                fprintf(stderr,
1192
 
                        "InnoDB: Error: trying to add tablespace %lu"
1193
 
                        " of name ", (ulong) id);
1194
 
                ut_print_filename(stderr, name);
1195
 
                fprintf(stderr, "\n"
1196
 
                        "InnoDB: to the tablespace memory cache,"
1197
 
                        " but tablespace\n"
1198
 
                        "InnoDB: %lu of name ", (ulong) space->id);
1199
 
                ut_print_filename(stderr, space->name);
1200
 
                fputs(" already exists in the tablespace\n"
1201
 
                      "InnoDB: memory cache!\n", stderr);
1202
 
 
1203
 
                mutex_exit(&fil_system->mutex);
1204
 
 
1205
 
                return(FALSE);
1206
 
        }
1207
 
 
1208
 
        space = mem_alloc(sizeof(fil_space_t));
1209
 
 
1210
 
        space->name = mem_strdup(name);
1211
 
        space->id = id;
1212
 
 
1213
 
        fil_system->tablespace_version++;
1214
 
        space->tablespace_version = fil_system->tablespace_version;
1215
 
        space->mark = FALSE;
1216
 
 
1217
 
        if (UNIV_LIKELY(purpose == FIL_TABLESPACE && !recv_recovery_on)
1218
 
            && UNIV_UNLIKELY(id > fil_system->max_assigned_id)) {
1219
 
                if (!fil_system->space_id_reuse_warned) {
1220
 
                        fil_system->space_id_reuse_warned = TRUE;
1221
 
 
1222
 
                        ut_print_timestamp(stderr);
1223
 
                        fprintf(stderr,
1224
 
                                "  InnoDB: Warning: allocated tablespace %lu,"
1225
 
                                " old maximum was %lu\n",
1226
 
                                (ulong) id,
1227
 
                                (ulong) fil_system->max_assigned_id);
1228
 
                }
1229
 
 
1230
 
                fil_system->max_assigned_id = id;
1231
 
        }
1232
 
 
1233
 
        space->stop_ios = FALSE;
1234
 
        space->stop_ibuf_merges = FALSE;
1235
 
        space->is_being_deleted = FALSE;
1236
 
        space->purpose = purpose;
1237
 
        space->size = 0;
1238
 
        space->flags = flags;
1239
 
 
1240
 
        space->n_reserved_extents = 0;
1241
 
 
1242
 
        space->n_pending_flushes = 0;
1243
 
        space->n_pending_ibuf_merges = 0;
1244
 
 
1245
 
        UT_LIST_INIT(space->chain);
1246
 
        space->magic_n = FIL_SPACE_MAGIC_N;
1247
 
 
1248
 
        rw_lock_create(fil_space_latch_key, &space->latch, SYNC_FSP);
1249
 
 
1250
 
        HASH_INSERT(fil_space_t, hash, fil_system->spaces, id, space);
1251
 
 
1252
 
        HASH_INSERT(fil_space_t, name_hash, fil_system->name_hash,
1253
 
                    ut_fold_string(name), space);
1254
 
        space->is_in_unflushed_spaces = FALSE;
1255
 
 
1256
 
        UT_LIST_ADD_LAST(space_list, fil_system->space_list, space);
1257
 
 
1258
 
        mutex_exit(&fil_system->mutex);
1259
 
 
1260
 
        return(TRUE);
1261
 
}
1262
 
 
1263
 
/*******************************************************************//**
1264
 
Assigns a new space id for a new single-table tablespace. This works simply by
1265
 
incrementing the global counter. If 4 billion id's is not enough, we may need
1266
 
to recycle id's.
1267
 
@return TRUE if assigned, FALSE if not */
1268
 
UNIV_INTERN
1269
 
ibool
1270
 
fil_assign_new_space_id(
1271
 
/*====================*/
1272
 
        ulint*  space_id)       /*!< in/out: space id */
1273
 
{
1274
 
        ulint   id;
1275
 
        ibool   success;
1276
 
 
1277
 
        mutex_enter(&fil_system->mutex);
1278
 
 
1279
 
        id = *space_id;
1280
 
 
1281
 
        if (id < fil_system->max_assigned_id) {
1282
 
                id = fil_system->max_assigned_id;
1283
 
        }
1284
 
 
1285
 
        id++;
1286
 
 
1287
 
        if (id > (SRV_LOG_SPACE_FIRST_ID / 2) && (id % 1000000UL == 0)) {
1288
 
                ut_print_timestamp(stderr);
1289
 
                fprintf(stderr,
1290
 
                        "InnoDB: Warning: you are running out of new"
1291
 
                        " single-table tablespace id's.\n"
1292
 
                        "InnoDB: Current counter is %lu and it"
1293
 
                        " must not exceed %lu!\n"
1294
 
                        "InnoDB: To reset the counter to zero"
1295
 
                        " you have to dump all your tables and\n"
1296
 
                        "InnoDB: recreate the whole InnoDB installation.\n",
1297
 
                        (ulong) id,
1298
 
                        (ulong) SRV_LOG_SPACE_FIRST_ID);
1299
 
        }
1300
 
 
1301
 
        success = (id < SRV_LOG_SPACE_FIRST_ID);
1302
 
 
1303
 
        if (success) {
1304
 
                *space_id = fil_system->max_assigned_id = id;
1305
 
        } else {
1306
 
                ut_print_timestamp(stderr);
1307
 
                fprintf(stderr,
1308
 
                        "InnoDB: You have run out of single-table"
1309
 
                        " tablespace id's!\n"
1310
 
                        "InnoDB: Current counter is %lu.\n"
1311
 
                        "InnoDB: To reset the counter to zero you"
1312
 
                        " have to dump all your tables and\n"
1313
 
                        "InnoDB: recreate the whole InnoDB installation.\n",
1314
 
                        (ulong) id);
1315
 
                *space_id = ULINT_UNDEFINED;
1316
 
        }
1317
 
 
1318
 
        mutex_exit(&fil_system->mutex);
1319
 
 
1320
 
        return(success);
1321
 
}
1322
 
 
1323
 
/*******************************************************************//**
1324
 
Frees a space object from the tablespace memory cache. Closes the files in
1325
 
the chain but does not delete them. There must not be any pending i/o's or
1326
 
flushes on the files.
1327
 
@return TRUE if success */
1328
 
static
1329
 
ibool
1330
 
fil_space_free(
1331
 
/*===========*/
1332
 
                                        /* out: TRUE if success */
1333
 
        ulint           id,             /* in: space id */
1334
 
        ibool           own_mutex)      /* in: TRUE if own system->mutex */
1335
 
{
1336
 
        fil_space_t*    space;
1337
 
        fil_space_t*    namespace;
1338
 
        fil_node_t*     fil_node;
1339
 
 
1340
 
        if (!own_mutex) {
1341
 
                mutex_enter(&fil_system->mutex);
1342
 
        }
1343
 
 
1344
 
        space = fil_space_get_by_id(id);
1345
 
 
1346
 
        if (!space) {
1347
 
                ut_print_timestamp(stderr);
1348
 
                fprintf(stderr,
1349
 
                        "  InnoDB: Error: trying to remove tablespace %lu"
1350
 
                        " from the cache but\n"
1351
 
                        "InnoDB: it is not there.\n", (ulong) id);
1352
 
 
1353
 
                mutex_exit(&fil_system->mutex);
1354
 
 
1355
 
                return(FALSE);
1356
 
        }
1357
 
 
1358
 
        HASH_DELETE(fil_space_t, hash, fil_system->spaces, id, space);
1359
 
 
1360
 
        namespace = fil_space_get_by_name(space->name);
1361
 
        ut_a(namespace);
1362
 
        ut_a(space == namespace);
1363
 
 
1364
 
        HASH_DELETE(fil_space_t, name_hash, fil_system->name_hash,
1365
 
                    ut_fold_string(space->name), space);
1366
 
 
1367
 
        if (space->is_in_unflushed_spaces) {
1368
 
                space->is_in_unflushed_spaces = FALSE;
1369
 
 
1370
 
                UT_LIST_REMOVE(unflushed_spaces, fil_system->unflushed_spaces,
1371
 
                               space);
1372
 
        }
1373
 
 
1374
 
        UT_LIST_REMOVE(space_list, fil_system->space_list, space);
1375
 
 
1376
 
        ut_a(space->magic_n == FIL_SPACE_MAGIC_N);
1377
 
        ut_a(0 == space->n_pending_flushes);
1378
 
 
1379
 
        fil_node = UT_LIST_GET_FIRST(space->chain);
1380
 
 
1381
 
        while (fil_node != NULL) {
1382
 
                fil_node_free(fil_node, fil_system, space);
1383
 
 
1384
 
                fil_node = UT_LIST_GET_FIRST(space->chain);
1385
 
        }
1386
 
 
1387
 
        ut_a(0 == UT_LIST_GET_LEN(space->chain));
1388
 
 
1389
 
        if (!own_mutex) {
1390
 
                mutex_exit(&fil_system->mutex);
1391
 
        }
1392
 
 
1393
 
        rw_lock_free(&(space->latch));
1394
 
 
1395
 
        mem_free(space->name);
1396
 
        mem_free(space);
1397
 
 
1398
 
        return(TRUE);
1399
 
}
1400
 
 
1401
 
/*******************************************************************//**
1402
 
Returns the size of the space in pages. The tablespace must be cached in the
1403
 
memory cache.
1404
 
@return space size, 0 if space not found */
1405
 
UNIV_INTERN
1406
 
ulint
1407
 
fil_space_get_size(
1408
 
/*===============*/
1409
 
        ulint   id)     /*!< in: space id */
1410
 
{
1411
 
        fil_node_t*     node;
1412
 
        fil_space_t*    space;
1413
 
        ulint           size;
1414
 
 
1415
 
        ut_ad(fil_system);
1416
 
 
1417
 
        fil_mutex_enter_and_prepare_for_io(id);
1418
 
 
1419
 
        space = fil_space_get_by_id(id);
1420
 
 
1421
 
        if (space == NULL) {
1422
 
                mutex_exit(&fil_system->mutex);
1423
 
 
1424
 
                return(0);
1425
 
        }
1426
 
 
1427
 
        if (space->size == 0 && space->purpose == FIL_TABLESPACE) {
1428
 
                ut_a(id != 0);
1429
 
 
1430
 
                ut_a(1 == UT_LIST_GET_LEN(space->chain));
1431
 
 
1432
 
                node = UT_LIST_GET_FIRST(space->chain);
1433
 
 
1434
 
                /* It must be a single-table tablespace and we have not opened
1435
 
                the file yet; the following calls will open it and update the
1436
 
                size fields */
1437
 
 
1438
 
                fil_node_prepare_for_io(node, fil_system, space);
1439
 
                fil_node_complete_io(node, fil_system, OS_FILE_READ);
1440
 
        }
1441
 
 
1442
 
        size = space->size;
1443
 
 
1444
 
        mutex_exit(&fil_system->mutex);
1445
 
 
1446
 
        return(size);
1447
 
}
1448
 
 
1449
 
/*******************************************************************//**
1450
 
Returns the flags of the space. The tablespace must be cached
1451
 
in the memory cache.
1452
 
@return flags, ULINT_UNDEFINED if space not found */
1453
 
UNIV_INTERN
1454
 
ulint
1455
 
fil_space_get_flags(
1456
 
/*================*/
1457
 
        ulint   id)     /*!< in: space id */
1458
 
{
1459
 
        fil_node_t*     node;
1460
 
        fil_space_t*    space;
1461
 
        ulint           flags;
1462
 
 
1463
 
        ut_ad(fil_system);
1464
 
 
1465
 
        if (UNIV_UNLIKELY(!id)) {
1466
 
                return(0);
1467
 
        }
1468
 
 
1469
 
        fil_mutex_enter_and_prepare_for_io(id);
1470
 
 
1471
 
        space = fil_space_get_by_id(id);
1472
 
 
1473
 
        if (space == NULL) {
1474
 
                mutex_exit(&fil_system->mutex);
1475
 
 
1476
 
                return(ULINT_UNDEFINED);
1477
 
        }
1478
 
 
1479
 
        if (space->size == 0 && space->purpose == FIL_TABLESPACE) {
1480
 
                ut_a(id != 0);
1481
 
 
1482
 
                ut_a(1 == UT_LIST_GET_LEN(space->chain));
1483
 
 
1484
 
                node = UT_LIST_GET_FIRST(space->chain);
1485
 
 
1486
 
                /* It must be a single-table tablespace and we have not opened
1487
 
                the file yet; the following calls will open it and update the
1488
 
                size fields */
1489
 
 
1490
 
                fil_node_prepare_for_io(node, fil_system, space);
1491
 
                fil_node_complete_io(node, fil_system, OS_FILE_READ);
1492
 
        }
1493
 
 
1494
 
        flags = space->flags;
1495
 
 
1496
 
        mutex_exit(&fil_system->mutex);
1497
 
 
1498
 
        return(flags);
1499
 
}
1500
 
 
1501
 
/*******************************************************************//**
1502
 
Returns the compressed page size of the space, or 0 if the space
1503
 
is not compressed. The tablespace must be cached in the memory cache.
1504
 
@return compressed page size, ULINT_UNDEFINED if space not found */
1505
 
UNIV_INTERN
1506
 
ulint
1507
 
fil_space_get_zip_size(
1508
 
/*===================*/
1509
 
        ulint   id)     /*!< in: space id */
1510
 
{
1511
 
        ulint   flags;
1512
 
 
1513
 
        flags = fil_space_get_flags(id);
1514
 
 
1515
 
        if (flags && flags != ULINT_UNDEFINED) {
1516
 
 
1517
 
                return(dict_table_flags_to_zip_size(flags));
1518
 
        }
1519
 
 
1520
 
        return(flags);
1521
 
}
1522
 
 
1523
 
/*******************************************************************//**
1524
 
Checks if the pair space, page_no refers to an existing page in a tablespace
1525
 
file space. The tablespace must be cached in the memory cache.
1526
 
@return TRUE if the address is meaningful */
1527
 
UNIV_INTERN
1528
 
ibool
1529
 
fil_check_adress_in_tablespace(
1530
 
/*===========================*/
1531
 
        ulint   id,     /*!< in: space id */
1532
 
        ulint   page_no)/*!< in: page number */
1533
 
{
1534
 
        if (fil_space_get_size(id) > page_no) {
1535
 
 
1536
 
                return(TRUE);
1537
 
        }
1538
 
 
1539
 
        return(FALSE);
1540
 
}
1541
 
 
1542
 
/****************************************************************//**
1543
 
Initializes the tablespace memory cache. */
1544
 
UNIV_INTERN
1545
 
void
1546
 
fil_init(
1547
 
/*=====*/
1548
 
        ulint   hash_size,      /*!< in: hash table size */
1549
 
        ulint   max_n_open)     /*!< in: max number of open files */
1550
 
{
1551
 
        ut_a(fil_system == NULL);
1552
 
 
1553
 
        ut_a(hash_size > 0);
1554
 
        ut_a(max_n_open > 0);
1555
 
 
1556
 
        fil_system = mem_zalloc(sizeof(fil_system_t));
1557
 
 
1558
 
        mutex_create(fil_system_mutex_key,
1559
 
                     &fil_system->mutex, SYNC_ANY_LATCH);
1560
 
 
1561
 
        fil_system->spaces = hash_create(hash_size);
1562
 
        fil_system->name_hash = hash_create(hash_size);
1563
 
 
1564
 
        UT_LIST_INIT(fil_system->LRU);
1565
 
 
1566
 
        fil_system->max_n_open = max_n_open;
1567
 
}
1568
 
 
1569
 
/*******************************************************************//**
1570
 
Opens all log files and system tablespace data files. They stay open until the
1571
 
database server shutdown. This should be called at a server startup after the
1572
 
space objects for the log and the system tablespace have been created. The
1573
 
purpose of this operation is to make sure we never run out of file descriptors
1574
 
if we need to read from the insert buffer or to write to the log. */
1575
 
UNIV_INTERN
1576
 
void
1577
 
fil_open_log_and_system_tablespace_files(void)
1578
 
/*==========================================*/
1579
 
{
1580
 
        fil_space_t*    space;
1581
 
        fil_node_t*     node;
1582
 
 
1583
 
        mutex_enter(&fil_system->mutex);
1584
 
 
1585
 
        space = UT_LIST_GET_FIRST(fil_system->space_list);
1586
 
 
1587
 
        while (space != NULL) {
1588
 
                if (space->purpose != FIL_TABLESPACE || space->id == 0) {
1589
 
                        node = UT_LIST_GET_FIRST(space->chain);
1590
 
 
1591
 
                        while (node != NULL) {
1592
 
                                if (!node->open) {
1593
 
                                        fil_node_open_file(node, fil_system,
1594
 
                                                           space);
1595
 
                                }
1596
 
                                if (fil_system->max_n_open
1597
 
                                    < 10 + fil_system->n_open) {
1598
 
                                        fprintf(stderr,
1599
 
                                                "InnoDB: Warning: you must"
1600
 
                                                " raise the value of"
1601
 
                                                " innodb_open_files in\n"
1602
 
                                                "InnoDB: my.cnf! Remember that"
1603
 
                                                " InnoDB keeps all log files"
1604
 
                                                " and all system\n"
1605
 
                                                "InnoDB: tablespace files open"
1606
 
                                                " for the whole time mysqld is"
1607
 
                                                " running, and\n"
1608
 
                                                "InnoDB: needs to open also"
1609
 
                                                " some .ibd files if the"
1610
 
                                                " file-per-table storage\n"
1611
 
                                                "InnoDB: model is used."
1612
 
                                                " Current open files %lu,"
1613
 
                                                " max allowed"
1614
 
                                                " open files %lu.\n",
1615
 
                                                (ulong) fil_system->n_open,
1616
 
                                                (ulong) fil_system->max_n_open);
1617
 
                                }
1618
 
                                node = UT_LIST_GET_NEXT(chain, node);
1619
 
                        }
1620
 
                }
1621
 
                space = UT_LIST_GET_NEXT(space_list, space);
1622
 
        }
1623
 
 
1624
 
        mutex_exit(&fil_system->mutex);
1625
 
}
1626
 
 
1627
 
/*******************************************************************//**
1628
 
Closes all open files. There must not be any pending i/o's or not flushed
1629
 
modifications in the files. */
1630
 
UNIV_INTERN
1631
 
void
1632
 
fil_close_all_files(void)
1633
 
/*=====================*/
1634
 
{
1635
 
        fil_space_t*    space;
1636
 
        fil_node_t*     node;
1637
 
 
1638
 
        mutex_enter(&fil_system->mutex);
1639
 
 
1640
 
        space = UT_LIST_GET_FIRST(fil_system->space_list);
1641
 
 
1642
 
        while (space != NULL) {
1643
 
                fil_space_t*    prev_space = space;
1644
 
 
1645
 
                node = UT_LIST_GET_FIRST(space->chain);
1646
 
 
1647
 
                while (node != NULL) {
1648
 
                        if (node->open) {
1649
 
                                fil_node_close_file(node, fil_system);
1650
 
                        }
1651
 
                        node = UT_LIST_GET_NEXT(chain, node);
1652
 
                }
1653
 
                space = UT_LIST_GET_NEXT(space_list, space);
1654
 
                fil_space_free(prev_space->id, TRUE);
1655
 
        }
1656
 
 
1657
 
        mutex_exit(&fil_system->mutex);
1658
 
}
1659
 
 
1660
 
/*******************************************************************//**
1661
 
Sets the max tablespace id counter if the given number is bigger than the
1662
 
previous value. */
1663
 
UNIV_INTERN
1664
 
void
1665
 
fil_set_max_space_id_if_bigger(
1666
 
/*===========================*/
1667
 
        ulint   max_id) /*!< in: maximum known id */
1668
 
{
1669
 
        if (max_id >= SRV_LOG_SPACE_FIRST_ID) {
1670
 
                fprintf(stderr,
1671
 
                        "InnoDB: Fatal error: max tablespace id"
1672
 
                        " is too high, %lu\n", (ulong) max_id);
1673
 
                ut_error;
1674
 
        }
1675
 
 
1676
 
        mutex_enter(&fil_system->mutex);
1677
 
 
1678
 
        if (fil_system->max_assigned_id < max_id) {
1679
 
 
1680
 
                fil_system->max_assigned_id = max_id;
1681
 
        }
1682
 
 
1683
 
        mutex_exit(&fil_system->mutex);
1684
 
}
1685
 
 
1686
 
/****************************************************************//**
1687
 
Writes the flushed lsn and the latest archived log number to the page header
1688
 
of the first page of a data file of the system tablespace (space 0),
1689
 
which is uncompressed. */
1690
 
static
1691
 
ulint
1692
 
fil_write_lsn_and_arch_no_to_file(
1693
 
/*==============================*/
1694
 
        ulint           sum_of_sizes,   /*!< in: combined size of previous files
1695
 
                                        in space, in database pages */
1696
 
        ib_uint64_t     lsn,            /*!< in: lsn to write */
1697
 
        ulint           arch_log_no __attribute__((unused)))
1698
 
                                        /*!< in: archived log number to write */
1699
 
{
1700
 
        byte*   buf1;
1701
 
        byte*   buf;
1702
 
 
1703
 
        buf1 = mem_alloc(2 * UNIV_PAGE_SIZE);
1704
 
        buf = ut_align(buf1, UNIV_PAGE_SIZE);
1705
 
 
1706
 
        fil_read(TRUE, 0, 0, sum_of_sizes, 0, UNIV_PAGE_SIZE, buf, NULL);
1707
 
 
1708
 
        mach_write_to_8(buf + FIL_PAGE_FILE_FLUSH_LSN, lsn);
1709
 
 
1710
 
        fil_write(TRUE, 0, 0, sum_of_sizes, 0, UNIV_PAGE_SIZE, buf, NULL);
1711
 
 
1712
 
        mem_free(buf1);
1713
 
 
1714
 
        return(DB_SUCCESS);
1715
 
}
1716
 
 
1717
 
/****************************************************************//**
1718
 
Writes the flushed lsn and the latest archived log number to the page
1719
 
header of the first page of each data file in the system tablespace.
1720
 
@return DB_SUCCESS or error number */
1721
 
UNIV_INTERN
1722
 
ulint
1723
 
fil_write_flushed_lsn_to_data_files(
1724
 
/*================================*/
1725
 
        ib_uint64_t     lsn,            /*!< in: lsn to write */
1726
 
        ulint           arch_log_no)    /*!< in: latest archived log
1727
 
                                        file number */
1728
 
{
1729
 
        fil_space_t*    space;
1730
 
        fil_node_t*     node;
1731
 
        ulint           sum_of_sizes;
1732
 
        ulint           err;
1733
 
 
1734
 
        mutex_enter(&fil_system->mutex);
1735
 
 
1736
 
        space = UT_LIST_GET_FIRST(fil_system->space_list);
1737
 
 
1738
 
        while (space) {
1739
 
                /* We only write the lsn to all existing data files which have
1740
 
                been open during the lifetime of the mysqld process; they are
1741
 
                represented by the space objects in the tablespace memory
1742
 
                cache. Note that all data files in the system tablespace 0 are
1743
 
                always open. */
1744
 
 
1745
 
                if (space->purpose == FIL_TABLESPACE
1746
 
                    && space->id == 0) {
1747
 
                        sum_of_sizes = 0;
1748
 
 
1749
 
                        node = UT_LIST_GET_FIRST(space->chain);
1750
 
                        while (node) {
1751
 
                                mutex_exit(&fil_system->mutex);
1752
 
 
1753
 
                                err = fil_write_lsn_and_arch_no_to_file(
1754
 
                                        sum_of_sizes, lsn, arch_log_no);
1755
 
                                if (err != DB_SUCCESS) {
1756
 
 
1757
 
                                        return(err);
1758
 
                                }
1759
 
 
1760
 
                                mutex_enter(&fil_system->mutex);
1761
 
 
1762
 
                                sum_of_sizes += node->size;
1763
 
                                node = UT_LIST_GET_NEXT(chain, node);
1764
 
                        }
1765
 
                }
1766
 
                space = UT_LIST_GET_NEXT(space_list, space);
1767
 
        }
1768
 
 
1769
 
        mutex_exit(&fil_system->mutex);
1770
 
 
1771
 
        return(DB_SUCCESS);
1772
 
}
1773
 
 
1774
 
/*******************************************************************//**
1775
 
Reads the flushed lsn and arch no fields from a data file at database
1776
 
startup. */
1777
 
UNIV_INTERN
1778
 
void
1779
 
fil_read_flushed_lsn_and_arch_log_no(
1780
 
/*=================================*/
1781
 
        os_file_t       data_file,              /*!< in: open data file */
1782
 
        ibool           one_read_already,       /*!< in: TRUE if min and max
1783
 
                                                parameters below already
1784
 
                                                contain sensible data */
1785
 
#ifdef UNIV_LOG_ARCHIVE
1786
 
        ulint*          min_arch_log_no,        /*!< in/out: */
1787
 
        ulint*          max_arch_log_no,        /*!< in/out: */
1788
 
#endif /* UNIV_LOG_ARCHIVE */
1789
 
        ib_uint64_t*    min_flushed_lsn,        /*!< in/out: */
1790
 
        ib_uint64_t*    max_flushed_lsn)        /*!< in/out: */
1791
 
{
1792
 
        byte*           buf;
1793
 
        byte*           buf2;
1794
 
        ib_uint64_t     flushed_lsn;
1795
 
 
1796
 
        buf2 = ut_malloc(2 * UNIV_PAGE_SIZE);
1797
 
        /* Align the memory for a possible read from a raw device */
1798
 
        buf = ut_align(buf2, UNIV_PAGE_SIZE);
1799
 
 
1800
 
        os_file_read(data_file, buf, 0, 0, UNIV_PAGE_SIZE);
1801
 
 
1802
 
        flushed_lsn = mach_read_from_8(buf + FIL_PAGE_FILE_FLUSH_LSN);
1803
 
 
1804
 
        ut_free(buf2);
1805
 
 
1806
 
        if (!one_read_already) {
1807
 
                *min_flushed_lsn = flushed_lsn;
1808
 
                *max_flushed_lsn = flushed_lsn;
1809
 
#ifdef UNIV_LOG_ARCHIVE
1810
 
                *min_arch_log_no = arch_log_no;
1811
 
                *max_arch_log_no = arch_log_no;
1812
 
#endif /* UNIV_LOG_ARCHIVE */
1813
 
                return;
1814
 
        }
1815
 
 
1816
 
        if (*min_flushed_lsn > flushed_lsn) {
1817
 
                *min_flushed_lsn = flushed_lsn;
1818
 
        }
1819
 
        if (*max_flushed_lsn < flushed_lsn) {
1820
 
                *max_flushed_lsn = flushed_lsn;
1821
 
        }
1822
 
#ifdef UNIV_LOG_ARCHIVE
1823
 
        if (*min_arch_log_no > arch_log_no) {
1824
 
                *min_arch_log_no = arch_log_no;
1825
 
        }
1826
 
        if (*max_arch_log_no < arch_log_no) {
1827
 
                *max_arch_log_no = arch_log_no;
1828
 
        }
1829
 
#endif /* UNIV_LOG_ARCHIVE */
1830
 
}
1831
 
 
1832
 
/*================ SINGLE-TABLE TABLESPACES ==========================*/
1833
 
 
1834
 
#ifndef UNIV_HOTBACKUP
1835
 
/*******************************************************************//**
1836
 
Increments the count of pending insert buffer page merges, if space is not
1837
 
being deleted.
1838
 
@return TRUE if being deleted, and ibuf merges should be skipped */
1839
 
UNIV_INTERN
1840
 
ibool
1841
 
fil_inc_pending_ibuf_merges(
1842
 
/*========================*/
1843
 
        ulint   id)     /*!< in: space id */
1844
 
{
1845
 
        fil_space_t*    space;
1846
 
 
1847
 
        mutex_enter(&fil_system->mutex);
1848
 
 
1849
 
        space = fil_space_get_by_id(id);
1850
 
 
1851
 
        if (space == NULL) {
1852
 
                fprintf(stderr,
1853
 
                        "InnoDB: Error: trying to do ibuf merge to a"
1854
 
                        " dropped tablespace %lu\n",
1855
 
                        (ulong) id);
1856
 
        }
1857
 
 
1858
 
        if (space == NULL || space->stop_ibuf_merges) {
1859
 
                mutex_exit(&fil_system->mutex);
1860
 
 
1861
 
                return(TRUE);
1862
 
        }
1863
 
 
1864
 
        space->n_pending_ibuf_merges++;
1865
 
 
1866
 
        mutex_exit(&fil_system->mutex);
1867
 
 
1868
 
        return(FALSE);
1869
 
}
1870
 
 
1871
 
/*******************************************************************//**
1872
 
Decrements the count of pending insert buffer page merges. */
1873
 
UNIV_INTERN
1874
 
void
1875
 
fil_decr_pending_ibuf_merges(
1876
 
/*=========================*/
1877
 
        ulint   id)     /*!< in: space id */
1878
 
{
1879
 
        fil_space_t*    space;
1880
 
 
1881
 
        mutex_enter(&fil_system->mutex);
1882
 
 
1883
 
        space = fil_space_get_by_id(id);
1884
 
 
1885
 
        if (space == NULL) {
1886
 
                fprintf(stderr,
1887
 
                        "InnoDB: Error: decrementing ibuf merge of a"
1888
 
                        " dropped tablespace %lu\n",
1889
 
                        (ulong) id);
1890
 
        }
1891
 
 
1892
 
        if (space != NULL) {
1893
 
                space->n_pending_ibuf_merges--;
1894
 
        }
1895
 
 
1896
 
        mutex_exit(&fil_system->mutex);
1897
 
}
1898
 
#endif /* !UNIV_HOTBACKUP */
1899
 
 
1900
 
/********************************************************//**
1901
 
Creates the database directory for a table if it does not exist yet. */
1902
 
static
1903
 
void
1904
 
fil_create_directory_for_tablename(
1905
 
/*===============================*/
1906
 
        const char*     name)   /*!< in: name in the standard
1907
 
                                'databasename/tablename' format */
1908
 
{
1909
 
        const char*     namend;
1910
 
        char*           path;
1911
 
        ulint           len;
1912
 
 
1913
 
        len = strlen(fil_path_to_mysql_datadir);
1914
 
        namend = strchr(name, '/');
1915
 
        ut_a(namend);
1916
 
        path = mem_alloc(len + (namend - name) + 2);
1917
 
 
1918
 
        memcpy(path, fil_path_to_mysql_datadir, len);
1919
 
        path[len] = '/';
1920
 
        memcpy(path + len + 1, name, namend - name);
1921
 
        path[len + (namend - name) + 1] = 0;
1922
 
 
1923
 
        srv_normalize_path_for_win(path);
1924
 
 
1925
 
        ut_a(os_file_create_directory(path, FALSE));
1926
 
        mem_free(path);
1927
 
}
1928
 
 
1929
 
#ifndef UNIV_HOTBACKUP
1930
 
/********************************************************//**
1931
 
Writes a log record about an .ibd file create/rename/delete. */
1932
 
static
1933
 
void
1934
 
fil_op_write_log(
1935
 
/*=============*/
1936
 
        ulint           type,           /*!< in: MLOG_FILE_CREATE,
1937
 
                                        MLOG_FILE_CREATE2,
1938
 
                                        MLOG_FILE_DELETE, or
1939
 
                                        MLOG_FILE_RENAME */
1940
 
        ulint           space_id,       /*!< in: space id */
1941
 
        ulint           log_flags,      /*!< in: redo log flags (stored
1942
 
                                        in the page number field) */
1943
 
        ulint           flags,          /*!< in: compressed page size
1944
 
                                        and file format
1945
 
                                        if type==MLOG_FILE_CREATE2, or 0 */
1946
 
        const char*     name,           /*!< in: table name in the familiar
1947
 
                                        'databasename/tablename' format, or
1948
 
                                        the file path in the case of
1949
 
                                        MLOG_FILE_DELETE */
1950
 
        const char*     new_name,       /*!< in: if type is MLOG_FILE_RENAME,
1951
 
                                        the new table name in the
1952
 
                                        'databasename/tablename' format */
1953
 
        mtr_t*          mtr)            /*!< in: mini-transaction handle */
1954
 
{
1955
 
        byte*   log_ptr;
1956
 
        ulint   len;
1957
 
 
1958
 
        log_ptr = mlog_open(mtr, 11 + 2 + 1);
1959
 
 
1960
 
        if (!log_ptr) {
1961
 
                /* Logging in mtr is switched off during crash recovery:
1962
 
                in that case mlog_open returns NULL */
1963
 
                return;
1964
 
        }
1965
 
 
1966
 
        log_ptr = mlog_write_initial_log_record_for_file_op(
1967
 
                type, space_id, log_flags, log_ptr, mtr);
1968
 
        if (type == MLOG_FILE_CREATE2) {
1969
 
                mach_write_to_4(log_ptr, flags);
1970
 
                log_ptr += 4;
1971
 
        }
1972
 
        /* Let us store the strings as null-terminated for easier readability
1973
 
        and handling */
1974
 
 
1975
 
        len = strlen(name) + 1;
1976
 
 
1977
 
        mach_write_to_2(log_ptr, len);
1978
 
        log_ptr += 2;
1979
 
        mlog_close(mtr, log_ptr);
1980
 
 
1981
 
        mlog_catenate_string(mtr, (byte*) name, len);
1982
 
 
1983
 
        if (type == MLOG_FILE_RENAME) {
1984
 
                len = strlen(new_name) + 1;
1985
 
                log_ptr = mlog_open(mtr, 2 + len);
1986
 
                ut_a(log_ptr);
1987
 
                mach_write_to_2(log_ptr, len);
1988
 
                log_ptr += 2;
1989
 
                mlog_close(mtr, log_ptr);
1990
 
 
1991
 
                mlog_catenate_string(mtr, (byte*) new_name, len);
1992
 
        }
1993
 
}
1994
 
#endif
1995
 
 
1996
 
/*******************************************************************//**
1997
 
Parses the body of a log record written about an .ibd file operation. That is,
1998
 
the log record part after the standard (type, space id, page no) header of the
1999
 
log record.
2000
 
 
2001
 
If desired, also replays the delete or rename operation if the .ibd file
2002
 
exists and the space id in it matches. Replays the create operation if a file
2003
 
at that path does not exist yet. If the database directory for the file to be
2004
 
created does not exist, then we create the directory, too.
2005
 
 
2006
 
Note that ibbackup --apply-log sets fil_path_to_mysql_datadir to point to the
2007
 
datadir that we should use in replaying the file operations.
2008
 
@return end of log record, or NULL if the record was not completely
2009
 
contained between ptr and end_ptr */
2010
 
UNIV_INTERN
2011
 
byte*
2012
 
fil_op_log_parse_or_replay(
2013
 
/*=======================*/
2014
 
        byte*   ptr,            /*!< in: buffer containing the log record body,
2015
 
                                or an initial segment of it, if the record does
2016
 
                                not fir completely between ptr and end_ptr */
2017
 
        byte*   end_ptr,        /*!< in: buffer end */
2018
 
        ulint   type,           /*!< in: the type of this log record */
2019
 
        ulint   space_id,       /*!< in: the space id of the tablespace in
2020
 
                                question, or 0 if the log record should
2021
 
                                only be parsed but not replayed */
2022
 
        ulint   log_flags)      /*!< in: redo log flags
2023
 
                                (stored in the page number parameter) */
2024
 
{
2025
 
        ulint           name_len;
2026
 
        ulint           new_name_len;
2027
 
        const char*     name;
2028
 
        const char*     new_name        = NULL;
2029
 
        ulint           flags           = 0;
2030
 
 
2031
 
        if (type == MLOG_FILE_CREATE2) {
2032
 
                if (end_ptr < ptr + 4) {
2033
 
 
2034
 
                        return(NULL);
2035
 
                }
2036
 
 
2037
 
                flags = mach_read_from_4(ptr);
2038
 
                ptr += 4;
2039
 
        }
2040
 
 
2041
 
        if (end_ptr < ptr + 2) {
2042
 
 
2043
 
                return(NULL);
2044
 
        }
2045
 
 
2046
 
        name_len = mach_read_from_2(ptr);
2047
 
 
2048
 
        ptr += 2;
2049
 
 
2050
 
        if (end_ptr < ptr + name_len) {
2051
 
 
2052
 
                return(NULL);
2053
 
        }
2054
 
 
2055
 
        name = (const char*) ptr;
2056
 
 
2057
 
        ptr += name_len;
2058
 
 
2059
 
        if (type == MLOG_FILE_RENAME) {
2060
 
                if (end_ptr < ptr + 2) {
2061
 
 
2062
 
                        return(NULL);
2063
 
                }
2064
 
 
2065
 
                new_name_len = mach_read_from_2(ptr);
2066
 
 
2067
 
                ptr += 2;
2068
 
 
2069
 
                if (end_ptr < ptr + new_name_len) {
2070
 
 
2071
 
                        return(NULL);
2072
 
                }
2073
 
 
2074
 
                new_name = (const char*) ptr;
2075
 
 
2076
 
                ptr += new_name_len;
2077
 
        }
2078
 
 
2079
 
        /* We managed to parse a full log record body */
2080
 
        /*
2081
 
        printf("Parsed log rec of type %lu space %lu\n"
2082
 
        "name %s\n", type, space_id, name);
2083
 
 
2084
 
        if (type == MLOG_FILE_RENAME) {
2085
 
        printf("new name %s\n", new_name);
2086
 
        }
2087
 
        */
2088
 
        if (!space_id) {
2089
 
 
2090
 
                return(ptr);
2091
 
        }
2092
 
 
2093
 
        /* Let us try to perform the file operation, if sensible. Note that
2094
 
        ibbackup has at this stage already read in all space id info to the
2095
 
        fil0fil.c data structures.
2096
 
 
2097
 
        NOTE that our algorithm is not guaranteed to work correctly if there
2098
 
        were renames of tables during the backup. See ibbackup code for more
2099
 
        on the problem. */
2100
 
 
2101
 
        switch (type) {
2102
 
        case MLOG_FILE_DELETE:
2103
 
                if (fil_tablespace_exists_in_mem(space_id)) {
2104
 
                        ut_a(fil_delete_tablespace(space_id));
2105
 
                }
2106
 
 
2107
 
                break;
2108
 
 
2109
 
        case MLOG_FILE_RENAME:
2110
 
                /* We do the rename based on space id, not old file name;
2111
 
                this should guarantee that after the log replay each .ibd file
2112
 
                has the correct name for the latest log sequence number; the
2113
 
                proof is left as an exercise :) */
2114
 
 
2115
 
                if (fil_tablespace_exists_in_mem(space_id)) {
2116
 
                        /* Create the database directory for the new name, if
2117
 
                        it does not exist yet */
2118
 
                        fil_create_directory_for_tablename(new_name);
2119
 
 
2120
 
                        /* Rename the table if there is not yet a tablespace
2121
 
                        with the same name */
2122
 
 
2123
 
                        if (fil_get_space_id_for_table(new_name)
2124
 
                            == ULINT_UNDEFINED) {
2125
 
                                /* We do not care of the old name, that is
2126
 
                                why we pass NULL as the first argument */
2127
 
                                if (!fil_rename_tablespace(NULL, space_id,
2128
 
                                                           new_name)) {
2129
 
                                        ut_error;
2130
 
                                }
2131
 
                        }
2132
 
                }
2133
 
 
2134
 
                break;
2135
 
 
2136
 
        case MLOG_FILE_CREATE:
2137
 
        case MLOG_FILE_CREATE2:
2138
 
                if (fil_tablespace_exists_in_mem(space_id)) {
2139
 
                        /* Do nothing */
2140
 
                } else if (fil_get_space_id_for_table(name)
2141
 
                           != ULINT_UNDEFINED) {
2142
 
                        /* Do nothing */
2143
 
                } else if (log_flags & MLOG_FILE_FLAG_TEMP) {
2144
 
                        /* Temporary table, do nothing */
2145
 
                } else {
2146
 
                        /* Create the database directory for name, if it does
2147
 
                        not exist yet */
2148
 
                        fil_create_directory_for_tablename(name);
2149
 
 
2150
 
                        if (fil_create_new_single_table_tablespace(
2151
 
                                    space_id, name, FALSE, flags,
2152
 
                                    FIL_IBD_FILE_INITIAL_SIZE) != DB_SUCCESS) {
2153
 
                                ut_error;
2154
 
                        }
2155
 
                }
2156
 
 
2157
 
                break;
2158
 
 
2159
 
        default:
2160
 
                ut_error;
2161
 
        }
2162
 
 
2163
 
        return(ptr);
2164
 
}
2165
 
 
2166
 
/*******************************************************************//**
2167
 
Deletes a single-table tablespace. The tablespace must be cached in the
2168
 
memory cache.
2169
 
@return TRUE if success */
2170
 
UNIV_INTERN
2171
 
ibool
2172
 
fil_delete_tablespace(
2173
 
/*==================*/
2174
 
        ulint   id)     /*!< in: space id */
2175
 
{
2176
 
        ibool           success;
2177
 
        fil_space_t*    space;
2178
 
        fil_node_t*     node;
2179
 
        ulint           count           = 0;
2180
 
        char*           path;
2181
 
 
2182
 
        ut_a(id != 0);
2183
 
stop_ibuf_merges:
2184
 
        mutex_enter(&fil_system->mutex);
2185
 
 
2186
 
        space = fil_space_get_by_id(id);
2187
 
 
2188
 
        if (space != NULL) {
2189
 
                space->stop_ibuf_merges = TRUE;
2190
 
 
2191
 
                if (space->n_pending_ibuf_merges == 0) {
2192
 
                        mutex_exit(&fil_system->mutex);
2193
 
 
2194
 
                        count = 0;
2195
 
 
2196
 
                        goto try_again;
2197
 
                } else {
2198
 
                        if (count > 5000) {
2199
 
                                ut_print_timestamp(stderr);
2200
 
                                fputs("  InnoDB: Warning: trying to"
2201
 
                                      " delete tablespace ", stderr);
2202
 
                                ut_print_filename(stderr, space->name);
2203
 
                                fprintf(stderr, ",\n"
2204
 
                                        "InnoDB: but there are %lu pending"
2205
 
                                        " ibuf merges on it.\n"
2206
 
                                        "InnoDB: Loop %lu.\n",
2207
 
                                        (ulong) space->n_pending_ibuf_merges,
2208
 
                                        (ulong) count);
2209
 
                        }
2210
 
 
2211
 
                        mutex_exit(&fil_system->mutex);
2212
 
 
2213
 
                        os_thread_sleep(20000);
2214
 
                        count++;
2215
 
 
2216
 
                        goto stop_ibuf_merges;
2217
 
                }
2218
 
        }
2219
 
 
2220
 
        mutex_exit(&fil_system->mutex);
2221
 
        count = 0;
2222
 
 
2223
 
try_again:
2224
 
        mutex_enter(&fil_system->mutex);
2225
 
 
2226
 
        space = fil_space_get_by_id(id);
2227
 
 
2228
 
        if (space == NULL) {
2229
 
                ut_print_timestamp(stderr);
2230
 
                fprintf(stderr,
2231
 
                        "  InnoDB: Error: cannot delete tablespace %lu\n"
2232
 
                        "InnoDB: because it is not found in the"
2233
 
                        " tablespace memory cache.\n",
2234
 
                        (ulong) id);
2235
 
 
2236
 
                mutex_exit(&fil_system->mutex);
2237
 
 
2238
 
                return(FALSE);
2239
 
        }
2240
 
 
2241
 
        ut_a(space);
2242
 
        ut_a(space->n_pending_ibuf_merges == 0);
2243
 
 
2244
 
        space->is_being_deleted = TRUE;
2245
 
 
2246
 
        ut_a(UT_LIST_GET_LEN(space->chain) == 1);
2247
 
        node = UT_LIST_GET_FIRST(space->chain);
2248
 
 
2249
 
        if (space->n_pending_flushes > 0 || node->n_pending > 0) {
2250
 
                if (count > 1000) {
2251
 
                        ut_print_timestamp(stderr);
2252
 
                        fputs("  InnoDB: Warning: trying to"
2253
 
                              " delete tablespace ", stderr);
2254
 
                        ut_print_filename(stderr, space->name);
2255
 
                        fprintf(stderr, ",\n"
2256
 
                                "InnoDB: but there are %lu flushes"
2257
 
                                " and %lu pending i/o's on it\n"
2258
 
                                "InnoDB: Loop %lu.\n",
2259
 
                                (ulong) space->n_pending_flushes,
2260
 
                                (ulong) node->n_pending,
2261
 
                                (ulong) count);
2262
 
                }
2263
 
                mutex_exit(&fil_system->mutex);
2264
 
                os_thread_sleep(20000);
2265
 
 
2266
 
                count++;
2267
 
 
2268
 
                goto try_again;
2269
 
        }
2270
 
 
2271
 
        path = mem_strdup(space->name);
2272
 
 
2273
 
        mutex_exit(&fil_system->mutex);
2274
 
#ifndef UNIV_HOTBACKUP
2275
 
        /* Invalidate in the buffer pool all pages belonging to the
2276
 
        tablespace. Since we have set space->is_being_deleted = TRUE, readahead
2277
 
        or ibuf merge can no longer read more pages of this tablespace to the
2278
 
        buffer pool. Thus we can clean the tablespace out of the buffer pool
2279
 
        completely and permanently. The flag is_being_deleted also prevents
2280
 
        fil_flush() from being applied to this tablespace. */
2281
 
 
2282
 
        buf_LRU_invalidate_tablespace(id);
2283
 
#endif
2284
 
        /* printf("Deleting tablespace %s id %lu\n", space->name, id); */
2285
 
 
2286
 
        success = fil_space_free(id, FALSE);
2287
 
 
2288
 
        if (success) {
2289
 
                success = os_file_delete(path);
2290
 
 
2291
 
                if (!success) {
2292
 
                        success = os_file_delete_if_exists(path);
2293
 
                }
2294
 
        }
2295
 
 
2296
 
        if (success) {
2297
 
#ifndef UNIV_HOTBACKUP
2298
 
                /* Write a log record about the deletion of the .ibd
2299
 
                file, so that ibbackup can replay it in the
2300
 
                --apply-log phase. We use a dummy mtr and the familiar
2301
 
                log write mechanism. */
2302
 
                mtr_t           mtr;
2303
 
 
2304
 
                /* When replaying the operation in ibbackup, do not try
2305
 
                to write any log record */
2306
 
                mtr_start(&mtr);
2307
 
 
2308
 
                fil_op_write_log(MLOG_FILE_DELETE, id, 0, 0, path, NULL, &mtr);
2309
 
                mtr_commit(&mtr);
2310
 
#endif
2311
 
                mem_free(path);
2312
 
 
2313
 
                return(TRUE);
2314
 
        }
2315
 
 
2316
 
        mem_free(path);
2317
 
 
2318
 
        return(FALSE);
2319
 
}
2320
 
 
2321
 
#ifndef UNIV_HOTBACKUP
2322
 
/*******************************************************************//**
2323
 
Discards a single-table tablespace. The tablespace must be cached in the
2324
 
memory cache. Discarding is like deleting a tablespace, but
2325
 
1) we do not drop the table from the data dictionary;
2326
 
2) we remove all insert buffer entries for the tablespace immediately; in DROP
2327
 
TABLE they are only removed gradually in the background;
2328
 
3) when the user does IMPORT TABLESPACE, the tablespace will have the same id
2329
 
as it originally had.
2330
 
@return TRUE if success */
2331
 
UNIV_INTERN
2332
 
ibool
2333
 
fil_discard_tablespace(
2334
 
/*===================*/
2335
 
        ulint   id)     /*!< in: space id */
2336
 
{
2337
 
        ibool   success;
2338
 
 
2339
 
        success = fil_delete_tablespace(id);
2340
 
 
2341
 
        if (!success) {
2342
 
                fprintf(stderr,
2343
 
                        "InnoDB: Warning: cannot delete tablespace %lu"
2344
 
                        " in DISCARD TABLESPACE.\n"
2345
 
                        "InnoDB: But let us remove the"
2346
 
                        " insert buffer entries for this tablespace.\n",
2347
 
                        (ulong) id);
2348
 
        }
2349
 
 
2350
 
        /* Remove all insert buffer entries for the tablespace */
2351
 
 
2352
 
        ibuf_delete_for_discarded_space(id);
2353
 
 
2354
 
        return(success);
2355
 
}
2356
 
#endif /* !UNIV_HOTBACKUP */
2357
 
 
2358
 
/*******************************************************************//**
2359
 
Renames the memory cache structures of a single-table tablespace.
2360
 
@return TRUE if success */
2361
 
static
2362
 
ibool
2363
 
fil_rename_tablespace_in_mem(
2364
 
/*=========================*/
2365
 
        fil_space_t*    space,  /*!< in: tablespace memory object */
2366
 
        fil_node_t*     node,   /*!< in: file node of that tablespace */
2367
 
        const char*     path)   /*!< in: new name */
2368
 
{
2369
 
        fil_space_t*    space2;
2370
 
        const char*     old_name        = space->name;
2371
 
 
2372
 
        ut_ad(mutex_own(&fil_system->mutex));
2373
 
 
2374
 
        space2 = fil_space_get_by_name(old_name);
2375
 
        if (space != space2) {
2376
 
                fputs("InnoDB: Error: cannot find ", stderr);
2377
 
                ut_print_filename(stderr, old_name);
2378
 
                fputs(" in tablespace memory cache\n", stderr);
2379
 
 
2380
 
                return(FALSE);
2381
 
        }
2382
 
 
2383
 
        space2 = fil_space_get_by_name(path);
2384
 
        if (space2 != NULL) {
2385
 
                fputs("InnoDB: Error: ", stderr);
2386
 
                ut_print_filename(stderr, path);
2387
 
                fputs(" is already in tablespace memory cache\n", stderr);
2388
 
 
2389
 
                return(FALSE);
2390
 
        }
2391
 
 
2392
 
        HASH_DELETE(fil_space_t, name_hash, fil_system->name_hash,
2393
 
                    ut_fold_string(space->name), space);
2394
 
        mem_free(space->name);
2395
 
        mem_free(node->name);
2396
 
 
2397
 
        space->name = mem_strdup(path);
2398
 
        node->name = mem_strdup(path);
2399
 
 
2400
 
        HASH_INSERT(fil_space_t, name_hash, fil_system->name_hash,
2401
 
                    ut_fold_string(path), space);
2402
 
        return(TRUE);
2403
 
}
2404
 
 
2405
 
/*******************************************************************//**
2406
 
Allocates a file name for a single-table tablespace. The string must be freed
2407
 
by caller with mem_free().
2408
 
@return own: file name */
2409
 
static
2410
 
char*
2411
 
fil_make_ibd_name(
2412
 
/*==============*/
2413
 
        const char*     name,           /*!< in: table name or a dir path of a
2414
 
                                        TEMPORARY table */
2415
 
        ibool           is_temp)        /*!< in: TRUE if it is a dir path */
2416
 
{
2417
 
        ulint   namelen         = strlen(name);
2418
 
        ulint   dirlen          = strlen(fil_path_to_mysql_datadir);
2419
 
        char*   filename        = mem_alloc(namelen + dirlen + sizeof "/.ibd");
2420
 
 
2421
 
        if (is_temp) {
2422
 
                memcpy(filename, name, namelen);
2423
 
                memcpy(filename + namelen, ".ibd", sizeof ".ibd");
2424
 
        } else {
2425
 
                memcpy(filename, fil_path_to_mysql_datadir, dirlen);
2426
 
                filename[dirlen] = '/';
2427
 
 
2428
 
                memcpy(filename + dirlen + 1, name, namelen);
2429
 
                memcpy(filename + dirlen + namelen + 1, ".ibd", sizeof ".ibd");
2430
 
        }
2431
 
 
2432
 
        srv_normalize_path_for_win(filename);
2433
 
 
2434
 
        return(filename);
2435
 
}
2436
 
 
2437
 
/*******************************************************************//**
2438
 
Renames a single-table tablespace. The tablespace must be cached in the
2439
 
tablespace memory cache.
2440
 
@return TRUE if success */
2441
 
UNIV_INTERN
2442
 
ibool
2443
 
fil_rename_tablespace(
2444
 
/*==================*/
2445
 
        const char*     old_name,       /*!< in: old table name in the standard
2446
 
                                        databasename/tablename format of
2447
 
                                        InnoDB, or NULL if we do the rename
2448
 
                                        based on the space id only */
2449
 
        ulint           id,             /*!< in: space id */
2450
 
        const char*     new_name)       /*!< in: new table name in the standard
2451
 
                                        databasename/tablename format
2452
 
                                        of InnoDB */
2453
 
{
2454
 
        ibool           success;
2455
 
        fil_space_t*    space;
2456
 
        fil_node_t*     node;
2457
 
        ulint           count           = 0;
2458
 
        char*           path;
2459
 
        ibool           old_name_was_specified          = TRUE;
2460
 
        char*           old_path;
2461
 
 
2462
 
        ut_a(id != 0);
2463
 
 
2464
 
        if (old_name == NULL) {
2465
 
                old_name = "(name not specified)";
2466
 
                old_name_was_specified = FALSE;
2467
 
        }
2468
 
retry:
2469
 
        count++;
2470
 
 
2471
 
        if (count > 1000) {
2472
 
                ut_print_timestamp(stderr);
2473
 
                fputs("  InnoDB: Warning: problems renaming ", stderr);
2474
 
                ut_print_filename(stderr, old_name);
2475
 
                fputs(" to ", stderr);
2476
 
                ut_print_filename(stderr, new_name);
2477
 
                fprintf(stderr, ", %lu iterations\n", (ulong) count);
2478
 
        }
2479
 
 
2480
 
        mutex_enter(&fil_system->mutex);
2481
 
 
2482
 
        space = fil_space_get_by_id(id);
2483
 
 
2484
 
        if (space == NULL) {
2485
 
                fprintf(stderr,
2486
 
                        "InnoDB: Error: cannot find space id %lu"
2487
 
                        " in the tablespace memory cache\n"
2488
 
                        "InnoDB: though the table ", (ulong) id);
2489
 
                ut_print_filename(stderr, old_name);
2490
 
                fputs(" in a rename operation should have that id\n", stderr);
2491
 
                mutex_exit(&fil_system->mutex);
2492
 
 
2493
 
                return(FALSE);
2494
 
        }
2495
 
 
2496
 
        if (count > 25000) {
2497
 
                space->stop_ios = FALSE;
2498
 
                mutex_exit(&fil_system->mutex);
2499
 
 
2500
 
                return(FALSE);
2501
 
        }
2502
 
 
2503
 
        /* We temporarily close the .ibd file because we do not trust that
2504
 
        operating systems can rename an open file. For the closing we have to
2505
 
        wait until there are no pending i/o's or flushes on the file. */
2506
 
 
2507
 
        space->stop_ios = TRUE;
2508
 
 
2509
 
        ut_a(UT_LIST_GET_LEN(space->chain) == 1);
2510
 
        node = UT_LIST_GET_FIRST(space->chain);
2511
 
 
2512
 
        if (node->n_pending > 0 || node->n_pending_flushes > 0) {
2513
 
                /* There are pending i/o's or flushes, sleep for a while and
2514
 
                retry */
2515
 
 
2516
 
                mutex_exit(&fil_system->mutex);
2517
 
 
2518
 
                os_thread_sleep(20000);
2519
 
 
2520
 
                goto retry;
2521
 
 
2522
 
        } else if (node->modification_counter > node->flush_counter) {
2523
 
                /* Flush the space */
2524
 
 
2525
 
                mutex_exit(&fil_system->mutex);
2526
 
 
2527
 
                os_thread_sleep(20000);
2528
 
 
2529
 
                fil_flush(id);
2530
 
 
2531
 
                goto retry;
2532
 
 
2533
 
        } else if (node->open) {
2534
 
                /* Close the file */
2535
 
 
2536
 
                fil_node_close_file(node, fil_system);
2537
 
        }
2538
 
 
2539
 
        /* Check that the old name in the space is right */
2540
 
 
2541
 
        if (old_name_was_specified) {
2542
 
                old_path = fil_make_ibd_name(old_name, FALSE);
2543
 
 
2544
 
                ut_a(strcmp(space->name, old_path) == 0);
2545
 
                ut_a(strcmp(node->name, old_path) == 0);
2546
 
        } else {
2547
 
                old_path = mem_strdup(space->name);
2548
 
        }
2549
 
 
2550
 
        /* Rename the tablespace and the node in the memory cache */
2551
 
        path = fil_make_ibd_name(new_name, FALSE);
2552
 
        success = fil_rename_tablespace_in_mem(space, node, path);
2553
 
 
2554
 
        if (success) {
2555
 
                success = os_file_rename(innodb_file_data_key, old_path, path);
2556
 
 
2557
 
                if (!success) {
2558
 
                        /* We have to revert the changes we made
2559
 
                        to the tablespace memory cache */
2560
 
 
2561
 
                        ut_a(fil_rename_tablespace_in_mem(space, node,
2562
 
                                                          old_path));
2563
 
                }
2564
 
        }
2565
 
 
2566
 
        mem_free(path);
2567
 
        mem_free(old_path);
2568
 
 
2569
 
        space->stop_ios = FALSE;
2570
 
 
2571
 
        mutex_exit(&fil_system->mutex);
2572
 
 
2573
 
#ifndef UNIV_HOTBACKUP
2574
 
        if (success) {
2575
 
                mtr_t           mtr;
2576
 
 
2577
 
                mtr_start(&mtr);
2578
 
 
2579
 
                fil_op_write_log(MLOG_FILE_RENAME, id, 0, 0, old_name, new_name,
2580
 
                                 &mtr);
2581
 
                mtr_commit(&mtr);
2582
 
        }
2583
 
#endif
2584
 
        return(success);
2585
 
}
2586
 
 
2587
 
/*******************************************************************//**
2588
 
Creates a new single-table tablespace to a database directory of MySQL.
2589
 
Database directories are under the 'datadir' of MySQL. The datadir is the
2590
 
directory of a running mysqld program. We can refer to it by simply the
2591
 
path '.'. Tables created with CREATE TEMPORARY TABLE we place in the temp
2592
 
dir of the mysqld server.
2593
 
@return DB_SUCCESS or error code */
2594
 
UNIV_INTERN
2595
 
ulint
2596
 
fil_create_new_single_table_tablespace(
2597
 
/*===================================*/
2598
 
        ulint           space_id,       /*!< in: space id */
2599
 
        const char*     tablename,      /*!< in: the table name in the usual
2600
 
                                        databasename/tablename format
2601
 
                                        of InnoDB, or a dir path to a temp
2602
 
                                        table */
2603
 
        ibool           is_temp,        /*!< in: TRUE if a table created with
2604
 
                                        CREATE TEMPORARY TABLE */
2605
 
        ulint           flags,          /*!< in: tablespace flags */
2606
 
        ulint           size)           /*!< in: the initial size of the
2607
 
                                        tablespace file in pages,
2608
 
                                        must be >= FIL_IBD_FILE_INITIAL_SIZE */
2609
 
{
2610
 
        os_file_t       file;
2611
 
        ibool           ret;
2612
 
        ulint           err;
2613
 
        byte*           buf2;
2614
 
        byte*           page;
2615
 
        ibool           success;
2616
 
        char*           path;
2617
 
 
2618
 
        ut_a(space_id > 0);
2619
 
        ut_a(space_id < SRV_LOG_SPACE_FIRST_ID);
2620
 
        ut_a(size >= FIL_IBD_FILE_INITIAL_SIZE);
2621
 
        /* The tablespace flags (FSP_SPACE_FLAGS) should be 0 for
2622
 
        ROW_FORMAT=COMPACT
2623
 
        ((table->flags & ~(~0 << DICT_TF_BITS)) == DICT_TF_COMPACT) and
2624
 
        ROW_FORMAT=REDUNDANT (table->flags == 0).  For any other
2625
 
        format, the tablespace flags should equal
2626
 
        (table->flags & ~(~0 << DICT_TF_BITS)). */
2627
 
        ut_a(flags != DICT_TF_COMPACT);
2628
 
        ut_a(!(flags & (~0UL << DICT_TF_BITS)));
2629
 
 
2630
 
        path = fil_make_ibd_name(tablename, is_temp);
2631
 
 
2632
 
        file = os_file_create(innodb_file_data_key, path,
2633
 
                              OS_FILE_CREATE, OS_FILE_NORMAL,
2634
 
                              OS_DATA_FILE, &ret);
2635
 
        if (ret == FALSE) {
2636
 
                ut_print_timestamp(stderr);
2637
 
                fputs("  InnoDB: Error creating file ", stderr);
2638
 
                ut_print_filename(stderr, path);
2639
 
                fputs(".\n", stderr);
2640
 
 
2641
 
                /* The following call will print an error message */
2642
 
 
2643
 
                err = os_file_get_last_error(TRUE);
2644
 
 
2645
 
                if (err == OS_FILE_ALREADY_EXISTS) {
2646
 
                        fputs("InnoDB: The file already exists though"
2647
 
                              " the corresponding table did not\n"
2648
 
                              "InnoDB: exist in the InnoDB data dictionary."
2649
 
                              " Have you moved InnoDB\n"
2650
 
                              "InnoDB: .ibd files around without using the"
2651
 
                              " SQL commands\n"
2652
 
                              "InnoDB: DISCARD TABLESPACE and"
2653
 
                              " IMPORT TABLESPACE, or did\n"
2654
 
                              "InnoDB: mysqld crash in the middle of"
2655
 
                              " CREATE TABLE? You can\n"
2656
 
                              "InnoDB: resolve the problem by"
2657
 
                              " removing the file ", stderr);
2658
 
                        ut_print_filename(stderr, path);
2659
 
                        fputs("\n"
2660
 
                              "InnoDB: under the 'datadir' of MySQL.\n",
2661
 
                              stderr);
2662
 
 
2663
 
                        mem_free(path);
2664
 
                        return(DB_TABLESPACE_ALREADY_EXISTS);
2665
 
                }
2666
 
 
2667
 
                if (err == OS_FILE_DISK_FULL) {
2668
 
 
2669
 
                        mem_free(path);
2670
 
                        return(DB_OUT_OF_FILE_SPACE);
2671
 
                }
2672
 
 
2673
 
                mem_free(path);
2674
 
                return(DB_ERROR);
2675
 
        }
2676
 
 
2677
 
        ret = os_file_set_size(path, file, size * UNIV_PAGE_SIZE, 0);
2678
 
 
2679
 
        if (!ret) {
2680
 
                err = DB_OUT_OF_FILE_SPACE;
2681
 
error_exit:
2682
 
                os_file_close(file);
2683
 
error_exit2:
2684
 
                os_file_delete(path);
2685
 
 
2686
 
                mem_free(path);
2687
 
                return(err);
2688
 
        }
2689
 
 
2690
 
        /* printf("Creating tablespace %s id %lu\n", path, space_id); */
2691
 
 
2692
 
        /* We have to write the space id to the file immediately and flush the
2693
 
        file to disk. This is because in crash recovery we must be aware what
2694
 
        tablespaces exist and what are their space id's, so that we can apply
2695
 
        the log records to the right file. It may take quite a while until
2696
 
        buffer pool flush algorithms write anything to the file and flush it to
2697
 
        disk. If we would not write here anything, the file would be filled
2698
 
        with zeros from the call of os_file_set_size(), until a buffer pool
2699
 
        flush would write to it. */
2700
 
 
2701
 
        buf2 = ut_malloc(3 * UNIV_PAGE_SIZE);
2702
 
        /* Align the memory for file i/o if we might have O_DIRECT set */
2703
 
        page = ut_align(buf2, UNIV_PAGE_SIZE);
2704
 
 
2705
 
        memset(page, '\0', UNIV_PAGE_SIZE);
2706
 
 
2707
 
        fsp_header_init_fields(page, space_id, flags);
2708
 
        mach_write_to_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, space_id);
2709
 
 
2710
 
        if (!(flags & DICT_TF_ZSSIZE_MASK)) {
2711
 
                buf_flush_init_for_writing(page, NULL, 0);
2712
 
                ret = os_file_write(path, file, page, 0, 0, UNIV_PAGE_SIZE);
2713
 
        } else {
2714
 
                page_zip_des_t  page_zip;
2715
 
                ulint           zip_size;
2716
 
 
2717
 
                zip_size = ((PAGE_ZIP_MIN_SIZE >> 1)
2718
 
                            << ((flags & DICT_TF_ZSSIZE_MASK)
2719
 
                                >> DICT_TF_ZSSIZE_SHIFT));
2720
 
 
2721
 
                page_zip_set_size(&page_zip, zip_size);
2722
 
                page_zip.data = page + UNIV_PAGE_SIZE;
2723
 
#ifdef UNIV_DEBUG
2724
 
                page_zip.m_start =
2725
 
#endif /* UNIV_DEBUG */
2726
 
                        page_zip.m_end = page_zip.m_nonempty =
2727
 
                        page_zip.n_blobs = 0;
2728
 
                buf_flush_init_for_writing(page, &page_zip, 0);
2729
 
                ret = os_file_write(path, file, page_zip.data, 0, 0, zip_size);
2730
 
        }
2731
 
 
2732
 
        ut_free(buf2);
2733
 
 
2734
 
        if (!ret) {
2735
 
                fputs("InnoDB: Error: could not write the first page"
2736
 
                      " to tablespace ", stderr);
2737
 
                ut_print_filename(stderr, path);
2738
 
                putc('\n', stderr);
2739
 
                err = DB_ERROR;
2740
 
                goto error_exit;
2741
 
        }
2742
 
 
2743
 
        ret = os_file_flush(file);
2744
 
 
2745
 
        if (!ret) {
2746
 
                fputs("InnoDB: Error: file flush of tablespace ", stderr);
2747
 
                ut_print_filename(stderr, path);
2748
 
                fputs(" failed\n", stderr);
2749
 
                err = DB_ERROR;
2750
 
                goto error_exit;
2751
 
        }
2752
 
 
2753
 
        os_file_close(file);
2754
 
 
2755
 
        success = fil_space_create(path, space_id, flags, FIL_TABLESPACE);
2756
 
 
2757
 
        if (!success) {
2758
 
                err = DB_ERROR;
2759
 
                goto error_exit2;
2760
 
        }
2761
 
 
2762
 
        fil_node_create(path, size, space_id, FALSE);
2763
 
 
2764
 
#ifndef UNIV_HOTBACKUP
2765
 
        {
2766
 
                mtr_t           mtr;
2767
 
 
2768
 
                mtr_start(&mtr);
2769
 
 
2770
 
                fil_op_write_log(flags
2771
 
                                 ? MLOG_FILE_CREATE2
2772
 
                                 : MLOG_FILE_CREATE,
2773
 
                                 space_id,
2774
 
                                 is_temp ? MLOG_FILE_FLAG_TEMP : 0,
2775
 
                                 flags,
2776
 
                                 tablename, NULL, &mtr);
2777
 
 
2778
 
                mtr_commit(&mtr);
2779
 
        }
2780
 
#endif
2781
 
        mem_free(path);
2782
 
        return(DB_SUCCESS);
2783
 
}
2784
 
 
2785
 
#ifndef UNIV_HOTBACKUP
2786
 
/********************************************************************//**
2787
 
It is possible, though very improbable, that the lsn's in the tablespace to be
2788
 
imported have risen above the current system lsn, if a lengthy purge, ibuf
2789
 
merge, or rollback was performed on a backup taken with ibbackup. If that is
2790
 
the case, reset page lsn's in the file. We assume that mysqld was shut down
2791
 
after it performed these cleanup operations on the .ibd file, so that it at
2792
 
the shutdown stamped the latest lsn to the FIL_PAGE_FILE_FLUSH_LSN in the
2793
 
first page of the .ibd file, and we can determine whether we need to reset the
2794
 
lsn's just by looking at that flush lsn.
2795
 
@return TRUE if success */
2796
 
UNIV_INTERN
2797
 
ibool
2798
 
fil_reset_too_high_lsns(
2799
 
/*====================*/
2800
 
        const char*     name,           /*!< in: table name in the
2801
 
                                        databasename/tablename format */
2802
 
        ib_uint64_t     current_lsn)    /*!< in: reset lsn's if the lsn stamped
2803
 
                                        to FIL_PAGE_FILE_FLUSH_LSN in the
2804
 
                                        first page is too high */
2805
 
{
2806
 
        os_file_t       file;
2807
 
        char*           filepath;
2808
 
        byte*           page;
2809
 
        byte*           buf2;
2810
 
        ib_uint64_t     flush_lsn;
2811
 
        ulint           space_id;
2812
 
        ib_int64_t      file_size;
2813
 
        ib_int64_t      offset;
2814
 
        ulint           zip_size;
2815
 
        ibool           success;
2816
 
        page_zip_des_t  page_zip;
2817
 
 
2818
 
        filepath = fil_make_ibd_name(name, FALSE);
2819
 
 
2820
 
        file = os_file_create_simple_no_error_handling(
2821
 
                innodb_file_data_key, filepath, OS_FILE_OPEN,
2822
 
                OS_FILE_READ_WRITE, &success);
2823
 
        if (!success) {
2824
 
                /* The following call prints an error message */
2825
 
                os_file_get_last_error(TRUE);
2826
 
 
2827
 
                ut_print_timestamp(stderr);
2828
 
 
2829
 
                fputs("  InnoDB: Error: trying to open a table,"
2830
 
                      " but could not\n"
2831
 
                      "InnoDB: open the tablespace file ", stderr);
2832
 
                ut_print_filename(stderr, filepath);
2833
 
                fputs("!\n", stderr);
2834
 
                mem_free(filepath);
2835
 
 
2836
 
                return(FALSE);
2837
 
        }
2838
 
 
2839
 
        /* Read the first page of the tablespace */
2840
 
 
2841
 
        buf2 = ut_malloc(3 * UNIV_PAGE_SIZE);
2842
 
        /* Align the memory for file i/o if we might have O_DIRECT set */
2843
 
        page = ut_align(buf2, UNIV_PAGE_SIZE);
2844
 
 
2845
 
        success = os_file_read(file, page, 0, 0, UNIV_PAGE_SIZE);
2846
 
        if (!success) {
2847
 
 
2848
 
                goto func_exit;
2849
 
        }
2850
 
 
2851
 
        /* We have to read the file flush lsn from the header of the file */
2852
 
 
2853
 
        flush_lsn = mach_read_from_8(page + FIL_PAGE_FILE_FLUSH_LSN);
2854
 
 
2855
 
        if (current_lsn >= flush_lsn) {
2856
 
                /* Ok */
2857
 
                success = TRUE;
2858
 
 
2859
 
                goto func_exit;
2860
 
        }
2861
 
 
2862
 
        space_id = fsp_header_get_space_id(page);
2863
 
        zip_size = fsp_header_get_zip_size(page);
2864
 
 
2865
 
        page_zip_des_init(&page_zip);
2866
 
        page_zip_set_size(&page_zip, zip_size);
2867
 
        if (zip_size) {
2868
 
                page_zip.data = page + UNIV_PAGE_SIZE;
2869
 
        }
2870
 
 
2871
 
        ut_print_timestamp(stderr);
2872
 
        fprintf(stderr,
2873
 
                "  InnoDB: Flush lsn in the tablespace file %lu"
2874
 
                " to be imported\n"
2875
 
                "InnoDB: is %"PRIu64", which exceeds current"
2876
 
                " system lsn %"PRIu64".\n"
2877
 
                "InnoDB: We reset the lsn's in the file ",
2878
 
                (ulong) space_id,
2879
 
                flush_lsn, current_lsn);
2880
 
        ut_print_filename(stderr, filepath);
2881
 
        fputs(".\n", stderr);
2882
 
 
2883
 
        ut_a(ut_is_2pow(zip_size));
2884
 
        ut_a(zip_size <= UNIV_PAGE_SIZE);
2885
 
 
2886
 
        /* Loop through all the pages in the tablespace and reset the lsn and
2887
 
        the page checksum if necessary */
2888
 
 
2889
 
        file_size = os_file_get_size_as_iblonglong(file);
2890
 
 
2891
 
        for (offset = 0; offset < file_size;
2892
 
             offset += zip_size ? zip_size : UNIV_PAGE_SIZE) {
2893
 
                success = os_file_read(file, page,
2894
 
                                       (ulint)(offset & 0xFFFFFFFFUL),
2895
 
                                       (ulint)(offset >> 32),
2896
 
                                       zip_size ? zip_size : UNIV_PAGE_SIZE);
2897
 
                if (!success) {
2898
 
 
2899
 
                        goto func_exit;
2900
 
                }
2901
 
                if (mach_read_from_8(page + FIL_PAGE_LSN) > current_lsn) {
2902
 
                        /* We have to reset the lsn */
2903
 
 
2904
 
                        if (zip_size) {
2905
 
                                memcpy(page_zip.data, page, zip_size);
2906
 
                                buf_flush_init_for_writing(
2907
 
                                        page, &page_zip, current_lsn);
2908
 
                                success = os_file_write(
2909
 
                                        filepath, file, page_zip.data,
2910
 
                                        (ulint) offset & 0xFFFFFFFFUL,
2911
 
                                        (ulint) (offset >> 32), zip_size);
2912
 
                        } else {
2913
 
                                buf_flush_init_for_writing(
2914
 
                                        page, NULL, current_lsn);
2915
 
                                success = os_file_write(
2916
 
                                        filepath, file, page,
2917
 
                                        (ulint)(offset & 0xFFFFFFFFUL),
2918
 
                                        (ulint)(offset >> 32),
2919
 
                                        UNIV_PAGE_SIZE);
2920
 
                        }
2921
 
 
2922
 
                        if (!success) {
2923
 
 
2924
 
                                goto func_exit;
2925
 
                        }
2926
 
                }
2927
 
        }
2928
 
 
2929
 
        success = os_file_flush(file);
2930
 
        if (!success) {
2931
 
 
2932
 
                goto func_exit;
2933
 
        }
2934
 
 
2935
 
        /* We now update the flush_lsn stamp at the start of the file */
2936
 
        success = os_file_read(file, page, 0, 0,
2937
 
                               zip_size ? zip_size : UNIV_PAGE_SIZE);
2938
 
        if (!success) {
2939
 
 
2940
 
                goto func_exit;
2941
 
        }
2942
 
 
2943
 
        mach_write_to_8(page + FIL_PAGE_FILE_FLUSH_LSN, current_lsn);
2944
 
 
2945
 
        success = os_file_write(filepath, file, page, 0, 0,
2946
 
                                zip_size ? zip_size : UNIV_PAGE_SIZE);
2947
 
        if (!success) {
2948
 
 
2949
 
                goto func_exit;
2950
 
        }
2951
 
        success = os_file_flush(file);
2952
 
func_exit:
2953
 
        os_file_close(file);
2954
 
        ut_free(buf2);
2955
 
        mem_free(filepath);
2956
 
 
2957
 
        return(success);
2958
 
}
2959
 
 
2960
 
/********************************************************************//**
2961
 
Tries to open a single-table tablespace and optionally checks the space id is
2962
 
right in it. If does not succeed, prints an error message to the .err log. This
2963
 
function is used to open a tablespace when we start up mysqld, and also in
2964
 
IMPORT TABLESPACE.
2965
 
NOTE that we assume this operation is used either at the database startup
2966
 
or under the protection of the dictionary mutex, so that two users cannot
2967
 
race here. This operation does not leave the file associated with the
2968
 
tablespace open, but closes it after we have looked at the space id in it.
2969
 
@return TRUE if success */
2970
 
UNIV_INTERN
2971
 
ibool
2972
 
fil_open_single_table_tablespace(
2973
 
/*=============================*/
2974
 
        ibool           check_space_id, /*!< in: should we check that the space
2975
 
                                        id in the file is right; we assume
2976
 
                                        that this function runs much faster
2977
 
                                        if no check is made, since accessing
2978
 
                                        the file inode probably is much
2979
 
                                        faster (the OS caches them) than
2980
 
                                        accessing the first page of the file */
2981
 
        ulint           id,             /*!< in: space id */
2982
 
        ulint           flags,          /*!< in: tablespace flags */
2983
 
        const char*     name)           /*!< in: table name in the
2984
 
                                        databasename/tablename format */
2985
 
{
2986
 
        os_file_t       file;
2987
 
        char*           filepath;
2988
 
        ibool           success;
2989
 
        byte*           buf2;
2990
 
        byte*           page;
2991
 
        ulint           space_id;
2992
 
        ulint           space_flags;
2993
 
 
2994
 
        filepath = fil_make_ibd_name(name, FALSE);
2995
 
 
2996
 
        /* The tablespace flags (FSP_SPACE_FLAGS) should be 0 for
2997
 
        ROW_FORMAT=COMPACT
2998
 
        ((table->flags & ~(~0 << DICT_TF_BITS)) == DICT_TF_COMPACT) and
2999
 
        ROW_FORMAT=REDUNDANT (table->flags == 0).  For any other
3000
 
        format, the tablespace flags should equal
3001
 
        (table->flags & ~(~0 << DICT_TF_BITS)). */
3002
 
        ut_a(flags != DICT_TF_COMPACT);
3003
 
        ut_a(!(flags & (~0UL << DICT_TF_BITS)));
3004
 
 
3005
 
        file = os_file_create_simple_no_error_handling(
3006
 
                innodb_file_data_key, filepath, OS_FILE_OPEN,
3007
 
                OS_FILE_READ_ONLY, &success);
3008
 
        if (!success) {
3009
 
                /* The following call prints an error message */
3010
 
                os_file_get_last_error(TRUE);
3011
 
 
3012
 
                ut_print_timestamp(stderr);
3013
 
 
3014
 
                fputs("  InnoDB: Error: trying to open a table,"
3015
 
                      " but could not\n"
3016
 
                      "InnoDB: open the tablespace file ", stderr);
3017
 
                ut_print_filename(stderr, filepath);
3018
 
                fputs("!\n"
3019
 
                      "InnoDB: Have you moved InnoDB .ibd files around"
3020
 
                      " without using the\n"
3021
 
                      "InnoDB: commands DISCARD TABLESPACE and"
3022
 
                      " IMPORT TABLESPACE?\n"
3023
 
                      "InnoDB: It is also possible that this is"
3024
 
                      " a temporary table #sql...,\n"
3025
 
                      "InnoDB: and MySQL removed the .ibd file for this.\n"
3026
 
                      "InnoDB: Please refer to\n"
3027
 
                      "InnoDB: " REFMAN "innodb-troubleshooting-datadict.html\n"
3028
 
                      "InnoDB: for how to resolve the issue.\n", stderr);
3029
 
 
3030
 
                mem_free(filepath);
3031
 
 
3032
 
                return(FALSE);
3033
 
        }
3034
 
 
3035
 
        if (!check_space_id) {
3036
 
                space_id = id;
3037
 
 
3038
 
                goto skip_check;
3039
 
        }
3040
 
 
3041
 
        /* Read the first page of the tablespace */
3042
 
 
3043
 
        buf2 = ut_malloc(2 * UNIV_PAGE_SIZE);
3044
 
        /* Align the memory for file i/o if we might have O_DIRECT set */
3045
 
        page = ut_align(buf2, UNIV_PAGE_SIZE);
3046
 
 
3047
 
        success = os_file_read(file, page, 0, 0, UNIV_PAGE_SIZE);
3048
 
 
3049
 
        /* We have to read the tablespace id and flags from the file. */
3050
 
 
3051
 
        space_id = fsp_header_get_space_id(page);
3052
 
        space_flags = fsp_header_get_flags(page);
3053
 
 
3054
 
        ut_free(buf2);
3055
 
 
3056
 
        if (UNIV_UNLIKELY(space_id != id
3057
 
                          || space_flags != (flags & ~(~0 << DICT_TF_BITS)))) {
3058
 
                ut_print_timestamp(stderr);
3059
 
 
3060
 
                fputs("  InnoDB: Error: tablespace id and flags in file ",
3061
 
                      stderr);
3062
 
                ut_print_filename(stderr, filepath);
3063
 
                fprintf(stderr, " are %lu and %lu, but in the InnoDB\n"
3064
 
                        "InnoDB: data dictionary they are %lu and %lu.\n"
3065
 
                        "InnoDB: Have you moved InnoDB .ibd files"
3066
 
                        " around without using the\n"
3067
 
                        "InnoDB: commands DISCARD TABLESPACE and"
3068
 
                        " IMPORT TABLESPACE?\n"
3069
 
                        "InnoDB: Please refer to\n"
3070
 
                        "InnoDB: " REFMAN "innodb-troubleshooting-datadict.html\n"
3071
 
                        "InnoDB: for how to resolve the issue.\n",
3072
 
                        (ulong) space_id, (ulong) space_flags,
3073
 
                        (ulong) id, (ulong) flags);
3074
 
 
3075
 
                success = FALSE;
3076
 
 
3077
 
                goto func_exit;
3078
 
        }
3079
 
 
3080
 
skip_check:
3081
 
        success = fil_space_create(filepath, space_id, flags, FIL_TABLESPACE);
3082
 
 
3083
 
        if (!success) {
3084
 
                goto func_exit;
3085
 
        }
3086
 
 
3087
 
        /* We do not measure the size of the file, that is why we pass the 0
3088
 
        below */
3089
 
 
3090
 
        fil_node_create(filepath, 0, space_id, FALSE);
3091
 
func_exit:
3092
 
        os_file_close(file);
3093
 
        mem_free(filepath);
3094
 
 
3095
 
        return(success);
3096
 
}
3097
 
#endif /* !UNIV_HOTBACKUP */
3098
 
 
3099
 
#ifdef UNIV_HOTBACKUP
3100
 
/*******************************************************************//**
3101
 
Allocates a file name for an old version of a single-table tablespace.
3102
 
The string must be freed by caller with mem_free()!
3103
 
@return own: file name */
3104
 
static
3105
 
char*
3106
 
fil_make_ibbackup_old_name(
3107
 
/*=======================*/
3108
 
        const char*     name)           /*!< in: original file name */
3109
 
{
3110
 
        static const char suffix[] = "_ibbackup_old_vers_";
3111
 
        ulint   len     = strlen(name);
3112
 
        char*   path    = mem_alloc(len + (15 + sizeof suffix));
3113
 
 
3114
 
        memcpy(path, name, len);
3115
 
        memcpy(path + len, suffix, (sizeof suffix) - 1);
3116
 
        ut_sprintf_timestamp_without_extra_chars(path + len + sizeof suffix);
3117
 
        return(path);
3118
 
}
3119
 
#endif /* UNIV_HOTBACKUP */
3120
 
 
3121
 
/********************************************************************//**
3122
 
Opens an .ibd file and adds the associated single-table tablespace to the
3123
 
InnoDB fil0fil.c data structures. */
3124
 
static
3125
 
void
3126
 
fil_load_single_table_tablespace(
3127
 
/*=============================*/
3128
 
        const char*     dbname,         /*!< in: database name */
3129
 
        const char*     filename)       /*!< in: file name (not a path),
3130
 
                                        including the .ibd extension */
3131
 
{
3132
 
        os_file_t       file;
3133
 
        char*           filepath;
3134
 
        ibool           success;
3135
 
        byte*           buf2;
3136
 
        byte*           page;
3137
 
        ulint           space_id;
3138
 
        ulint           flags;
3139
 
        ulint           size_low;
3140
 
        ulint           size_high;
3141
 
        ib_int64_t      size;
3142
 
#ifdef UNIV_HOTBACKUP
3143
 
        fil_space_t*    space;
3144
 
#endif
3145
 
        filepath = mem_alloc(strlen(dbname) + strlen(filename)
3146
 
                             + strlen(fil_path_to_mysql_datadir) + 3);
3147
 
 
3148
 
        sprintf(filepath, "%s/%s/%s", fil_path_to_mysql_datadir, dbname,
3149
 
                filename);
3150
 
        srv_normalize_path_for_win(filepath);
3151
 
#ifdef __WIN__
3152
 
# ifndef UNIV_HOTBACKUP
3153
 
        /* If lower_case_table_names is 0 or 2, then MySQL allows database
3154
 
        directory names with upper case letters. On Windows, all table and
3155
 
        database names in InnoDB are internally always in lower case. Put the
3156
 
        file path to lower case, so that we are consistent with InnoDB's
3157
 
        internal data dictionary. */
3158
 
 
3159
 
        dict_casedn_str(filepath);
3160
 
# endif /* !UNIV_HOTBACKUP */
3161
 
#endif
3162
 
        file = os_file_create_simple_no_error_handling(
3163
 
                innodb_file_data_key, filepath, OS_FILE_OPEN,
3164
 
                OS_FILE_READ_ONLY, &success);
3165
 
        if (!success) {
3166
 
                /* The following call prints an error message */
3167
 
                os_file_get_last_error(TRUE);
3168
 
 
3169
 
                fprintf(stderr,
3170
 
                        "InnoDB: Error: could not open single-table tablespace"
3171
 
                        " file\n"
3172
 
                        "InnoDB: %s!\n"
3173
 
                        "InnoDB: We do not continue the crash recovery,"
3174
 
                        " because the table may become\n"
3175
 
                        "InnoDB: corrupt if we cannot apply the log records"
3176
 
                        " in the InnoDB log to it.\n"
3177
 
                        "InnoDB: To fix the problem and start mysqld:\n"
3178
 
                        "InnoDB: 1) If there is a permission problem"
3179
 
                        " in the file and mysqld cannot\n"
3180
 
                        "InnoDB: open the file, you should"
3181
 
                        " modify the permissions.\n"
3182
 
                        "InnoDB: 2) If the table is not needed, or you can"
3183
 
                        " restore it from a backup,\n"
3184
 
                        "InnoDB: then you can remove the .ibd file,"
3185
 
                        " and InnoDB will do a normal\n"
3186
 
                        "InnoDB: crash recovery and ignore that table.\n"
3187
 
                        "InnoDB: 3) If the file system or the"
3188
 
                        " disk is broken, and you cannot remove\n"
3189
 
                        "InnoDB: the .ibd file, you can set"
3190
 
                        " innodb_force_recovery > 0 in my.cnf\n"
3191
 
                        "InnoDB: and force InnoDB to continue crash"
3192
 
                        " recovery here.\n", filepath);
3193
 
 
3194
 
                mem_free(filepath);
3195
 
 
3196
 
                if (srv_force_recovery > 0) {
3197
 
                        fprintf(stderr,
3198
 
                                "InnoDB: innodb_force_recovery"
3199
 
                                " was set to %lu. Continuing crash recovery\n"
3200
 
                                "InnoDB: even though we cannot access"
3201
 
                                " the .ibd file of this table.\n",
3202
 
                                srv_force_recovery);
3203
 
                        return;
3204
 
                }
3205
 
 
3206
 
                exit(1);
3207
 
        }
3208
 
 
3209
 
        success = os_file_get_size(file, &size_low, &size_high);
3210
 
 
3211
 
        if (!success) {
3212
 
                /* The following call prints an error message */
3213
 
                os_file_get_last_error(TRUE);
3214
 
 
3215
 
                fprintf(stderr,
3216
 
                        "InnoDB: Error: could not measure the size"
3217
 
                        " of single-table tablespace file\n"
3218
 
                        "InnoDB: %s!\n"
3219
 
                        "InnoDB: We do not continue crash recovery,"
3220
 
                        " because the table will become\n"
3221
 
                        "InnoDB: corrupt if we cannot apply the log records"
3222
 
                        " in the InnoDB log to it.\n"
3223
 
                        "InnoDB: To fix the problem and start mysqld:\n"
3224
 
                        "InnoDB: 1) If there is a permission problem"
3225
 
                        " in the file and mysqld cannot\n"
3226
 
                        "InnoDB: access the file, you should"
3227
 
                        " modify the permissions.\n"
3228
 
                        "InnoDB: 2) If the table is not needed,"
3229
 
                        " or you can restore it from a backup,\n"
3230
 
                        "InnoDB: then you can remove the .ibd file,"
3231
 
                        " and InnoDB will do a normal\n"
3232
 
                        "InnoDB: crash recovery and ignore that table.\n"
3233
 
                        "InnoDB: 3) If the file system or the disk is broken,"
3234
 
                        " and you cannot remove\n"
3235
 
                        "InnoDB: the .ibd file, you can set"
3236
 
                        " innodb_force_recovery > 0 in my.cnf\n"
3237
 
                        "InnoDB: and force InnoDB to continue"
3238
 
                        " crash recovery here.\n", filepath);
3239
 
 
3240
 
                os_file_close(file);
3241
 
                mem_free(filepath);
3242
 
 
3243
 
                if (srv_force_recovery > 0) {
3244
 
                        fprintf(stderr,
3245
 
                                "InnoDB: innodb_force_recovery"
3246
 
                                " was set to %lu. Continuing crash recovery\n"
3247
 
                                "InnoDB: even though we cannot access"
3248
 
                                " the .ibd file of this table.\n",
3249
 
                                srv_force_recovery);
3250
 
                        return;
3251
 
                }
3252
 
 
3253
 
                exit(1);
3254
 
        }
3255
 
 
3256
 
        /* TODO: What to do in other cases where we cannot access an .ibd
3257
 
        file during a crash recovery? */
3258
 
 
3259
 
        /* Every .ibd file is created >= 4 pages in size. Smaller files
3260
 
        cannot be ok. */
3261
 
 
3262
 
        size = (((ib_int64_t)size_high) << 32) + (ib_int64_t)size_low;
3263
 
#ifndef UNIV_HOTBACKUP
3264
 
        if (size < FIL_IBD_FILE_INITIAL_SIZE * UNIV_PAGE_SIZE) {
3265
 
                fprintf(stderr,
3266
 
                        "InnoDB: Error: the size of single-table tablespace"
3267
 
                        " file %s\n"
3268
 
                        "InnoDB: is only %lu %lu, should be at least %lu!",
3269
 
                        filepath,
3270
 
                        (ulong) size_high,
3271
 
                        (ulong) size_low, (ulong) (4 * UNIV_PAGE_SIZE));
3272
 
                os_file_close(file);
3273
 
                mem_free(filepath);
3274
 
 
3275
 
                return;
3276
 
        }
3277
 
#endif
3278
 
        /* Read the first page of the tablespace if the size big enough */
3279
 
 
3280
 
        buf2 = ut_malloc(2 * UNIV_PAGE_SIZE);
3281
 
        /* Align the memory for file i/o if we might have O_DIRECT set */
3282
 
        page = ut_align(buf2, UNIV_PAGE_SIZE);
3283
 
 
3284
 
        if (size >= FIL_IBD_FILE_INITIAL_SIZE * UNIV_PAGE_SIZE) {
3285
 
                success = os_file_read(file, page, 0, 0, UNIV_PAGE_SIZE);
3286
 
 
3287
 
                /* We have to read the tablespace id from the file */
3288
 
 
3289
 
                space_id = fsp_header_get_space_id(page);
3290
 
                flags = fsp_header_get_flags(page);
3291
 
        } else {
3292
 
                space_id = ULINT_UNDEFINED;
3293
 
                flags = 0;
3294
 
        }
3295
 
 
3296
 
#ifndef UNIV_HOTBACKUP
3297
 
        if (space_id == ULINT_UNDEFINED || space_id == 0) {
3298
 
                fprintf(stderr,
3299
 
                        "InnoDB: Error: tablespace id %lu in file %s"
3300
 
                        " is not sensible\n",
3301
 
                        (ulong) space_id,
3302
 
                        filepath);
3303
 
                goto func_exit;
3304
 
        }
3305
 
#else
3306
 
        if (space_id == ULINT_UNDEFINED || space_id == 0) {
3307
 
                char*   new_path;
3308
 
 
3309
 
                fprintf(stderr,
3310
 
                        "InnoDB: Renaming tablespace %s of id %lu,\n"
3311
 
                        "InnoDB: to %s_ibbackup_old_vers_<timestamp>\n"
3312
 
                        "InnoDB: because its size %" PRId64 " is too small"
3313
 
                        " (< 4 pages 16 kB each),\n"
3314
 
                        "InnoDB: or the space id in the file header"
3315
 
                        " is not sensible.\n"
3316
 
                        "InnoDB: This can happen in an ibbackup run,"
3317
 
                        " and is not dangerous.\n",
3318
 
                        filepath, space_id, filepath, size);
3319
 
                os_file_close(file);
3320
 
 
3321
 
                new_path = fil_make_ibbackup_old_name(filepath);
3322
 
                ut_a(os_file_rename(innodb_file_data_key, filepath, new_path));
3323
 
 
3324
 
                ut_free(buf2);
3325
 
                mem_free(filepath);
3326
 
                mem_free(new_path);
3327
 
 
3328
 
                return;
3329
 
        }
3330
 
 
3331
 
        /* A backup may contain the same space several times, if the space got
3332
 
        renamed at a sensitive time. Since it is enough to have one version of
3333
 
        the space, we rename the file if a space with the same space id
3334
 
        already exists in the tablespace memory cache. We rather rename the
3335
 
        file than delete it, because if there is a bug, we do not want to
3336
 
        destroy valuable data. */
3337
 
 
3338
 
        mutex_enter(&fil_system->mutex);
3339
 
 
3340
 
        space = fil_space_get_by_id(space_id);
3341
 
 
3342
 
        if (space) {
3343
 
                char*   new_path;
3344
 
 
3345
 
                fprintf(stderr,
3346
 
                        "InnoDB: Renaming tablespace %s of id %lu,\n"
3347
 
                        "InnoDB: to %s_ibbackup_old_vers_<timestamp>\n"
3348
 
                        "InnoDB: because space %s with the same id\n"
3349
 
                        "InnoDB: was scanned earlier. This can happen"
3350
 
                        " if you have renamed tables\n"
3351
 
                        "InnoDB: during an ibbackup run.\n",
3352
 
                        filepath, space_id, filepath,
3353
 
                        space->name);
3354
 
                os_file_close(file);
3355
 
 
3356
 
                new_path = fil_make_ibbackup_old_name(filepath);
3357
 
 
3358
 
                mutex_exit(&fil_system->mutex);
3359
 
 
3360
 
                ut_a(os_file_rename(innodb_file_data_key, filepath, new_path));
3361
 
 
3362
 
                ut_free(buf2);
3363
 
                mem_free(filepath);
3364
 
                mem_free(new_path);
3365
 
 
3366
 
                return;
3367
 
        }
3368
 
        mutex_exit(&fil_system->mutex);
3369
 
#endif
3370
 
        success = fil_space_create(filepath, space_id, flags, FIL_TABLESPACE);
3371
 
 
3372
 
        if (!success) {
3373
 
 
3374
 
                if (srv_force_recovery > 0) {
3375
 
                        fprintf(stderr,
3376
 
                                "InnoDB: innodb_force_recovery"
3377
 
                                " was set to %lu. Continuing crash recovery\n"
3378
 
                                "InnoDB: even though the tablespace creation"
3379
 
                                " of this table failed.\n",
3380
 
                                srv_force_recovery);
3381
 
                        goto func_exit;
3382
 
                }
3383
 
 
3384
 
                exit(1);
3385
 
        }
3386
 
 
3387
 
        /* We do not use the size information we have about the file, because
3388
 
        the rounding formula for extents and pages is somewhat complex; we
3389
 
        let fil_node_open() do that task. */
3390
 
 
3391
 
        fil_node_create(filepath, 0, space_id, FALSE);
3392
 
func_exit:
3393
 
        os_file_close(file);
3394
 
        ut_free(buf2);
3395
 
        mem_free(filepath);
3396
 
}
3397
 
 
3398
 
/***********************************************************************//**
3399
 
A fault-tolerant function that tries to read the next file name in the
3400
 
directory. We retry 100 times if os_file_readdir_next_file() returns -1. The
3401
 
idea is to read as much good data as we can and jump over bad data.
3402
 
@return 0 if ok, -1 if error even after the retries, 1 if at the end
3403
 
of the directory */
3404
 
static
3405
 
int
3406
 
fil_file_readdir_next_file(
3407
 
/*=======================*/
3408
 
        ulint*          err,    /*!< out: this is set to DB_ERROR if an error
3409
 
                                was encountered, otherwise not changed */
3410
 
        const char*     dirname,/*!< in: directory name or path */
3411
 
        os_file_dir_t   dir,    /*!< in: directory stream */
3412
 
        os_file_stat_t* info)   /*!< in/out: buffer where the info is returned */
3413
 
{
3414
 
        ulint   i;
3415
 
        int     ret;
3416
 
 
3417
 
        for (i = 0; i < 100; i++) {
3418
 
                ret = os_file_readdir_next_file(dirname, dir, info);
3419
 
 
3420
 
                if (ret != -1) {
3421
 
 
3422
 
                        return(ret);
3423
 
                }
3424
 
 
3425
 
                fprintf(stderr,
3426
 
                        "InnoDB: Error: os_file_readdir_next_file()"
3427
 
                        " returned -1 in\n"
3428
 
                        "InnoDB: directory %s\n"
3429
 
                        "InnoDB: Crash recovery may have failed"
3430
 
                        " for some .ibd files!\n", dirname);
3431
 
 
3432
 
                *err = DB_ERROR;
3433
 
        }
3434
 
 
3435
 
        return(-1);
3436
 
}
3437
 
 
3438
 
/********************************************************************//**
3439
 
At the server startup, if we need crash recovery, scans the database
3440
 
directories under the MySQL datadir, looking for .ibd files. Those files are
3441
 
single-table tablespaces. We need to know the space id in each of them so that
3442
 
we know into which file we should look to check the contents of a page stored
3443
 
in the doublewrite buffer, also to know where to apply log records where the
3444
 
space id is != 0.
3445
 
@return DB_SUCCESS or error number */
3446
 
UNIV_INTERN
3447
 
ulint
3448
 
fil_load_single_table_tablespaces(void)
3449
 
/*===================================*/
3450
 
{
3451
 
        int             ret;
3452
 
        char*           dbpath          = NULL;
3453
 
        ulint           dbpath_len      = 100;
3454
 
        os_file_dir_t   dir;
3455
 
        os_file_dir_t   dbdir;
3456
 
        os_file_stat_t  dbinfo;
3457
 
        os_file_stat_t  fileinfo;
3458
 
        ulint           err             = DB_SUCCESS;
3459
 
 
3460
 
        /* The datadir of MySQL is always the default directory of mysqld */
3461
 
 
3462
 
        dir = os_file_opendir(fil_path_to_mysql_datadir, TRUE);
3463
 
 
3464
 
        if (dir == NULL) {
3465
 
 
3466
 
                return(DB_ERROR);
3467
 
        }
3468
 
 
3469
 
        dbpath = mem_alloc(dbpath_len);
3470
 
 
3471
 
        /* Scan all directories under the datadir. They are the database
3472
 
        directories of MySQL. */
3473
 
 
3474
 
        ret = fil_file_readdir_next_file(&err, fil_path_to_mysql_datadir, dir,
3475
 
                                         &dbinfo);
3476
 
        while (ret == 0) {
3477
 
                ulint len;
3478
 
                /* printf("Looking at %s in datadir\n", dbinfo.name); */
3479
 
 
3480
 
                if (dbinfo.type == OS_FILE_TYPE_FILE
3481
 
                    || dbinfo.type == OS_FILE_TYPE_UNKNOWN) {
3482
 
 
3483
 
                        goto next_datadir_item;
3484
 
                }
3485
 
 
3486
 
                /* We found a symlink or a directory; try opening it to see
3487
 
                if a symlink is a directory */
3488
 
 
3489
 
                len = strlen(fil_path_to_mysql_datadir)
3490
 
                        + strlen (dbinfo.name) + 2;
3491
 
                if (len > dbpath_len) {
3492
 
                        dbpath_len = len;
3493
 
 
3494
 
                        if (dbpath) {
3495
 
                                mem_free(dbpath);
3496
 
                        }
3497
 
 
3498
 
                        dbpath = mem_alloc(dbpath_len);
3499
 
                }
3500
 
                sprintf(dbpath, "%s/%s", fil_path_to_mysql_datadir,
3501
 
                        dbinfo.name);
3502
 
                srv_normalize_path_for_win(dbpath);
3503
 
 
3504
 
                dbdir = os_file_opendir(dbpath, FALSE);
3505
 
 
3506
 
                if (dbdir != NULL) {
3507
 
                        /* printf("Opened dir %s\n", dbinfo.name); */
3508
 
 
3509
 
                        /* We found a database directory; loop through it,
3510
 
                        looking for possible .ibd files in it */
3511
 
 
3512
 
                        ret = fil_file_readdir_next_file(&err, dbpath, dbdir,
3513
 
                                                         &fileinfo);
3514
 
                        while (ret == 0) {
3515
 
                                /* printf(
3516
 
                                "     Looking at file %s\n", fileinfo.name); */
3517
 
 
3518
 
                                if (fileinfo.type == OS_FILE_TYPE_DIR) {
3519
 
 
3520
 
                                        goto next_file_item;
3521
 
                                }
3522
 
 
3523
 
                                /* We found a symlink or a file */
3524
 
                                if (strlen(fileinfo.name) > 4
3525
 
                                    && 0 == strcmp(fileinfo.name
3526
 
                                                   + strlen(fileinfo.name) - 4,
3527
 
                                                   ".ibd")) {
3528
 
                                        /* The name ends in .ibd; try opening
3529
 
                                        the file */
3530
 
                                        fil_load_single_table_tablespace(
3531
 
                                                dbinfo.name, fileinfo.name);
3532
 
                                }
3533
 
next_file_item:
3534
 
                                ret = fil_file_readdir_next_file(&err,
3535
 
                                                                 dbpath, dbdir,
3536
 
                                                                 &fileinfo);
3537
 
                        }
3538
 
 
3539
 
                        if (0 != os_file_closedir(dbdir)) {
3540
 
                                fputs("InnoDB: Warning: could not"
3541
 
                                      " close database directory ", stderr);
3542
 
                                ut_print_filename(stderr, dbpath);
3543
 
                                putc('\n', stderr);
3544
 
 
3545
 
                                err = DB_ERROR;
3546
 
                        }
3547
 
                }
3548
 
 
3549
 
next_datadir_item:
3550
 
                ret = fil_file_readdir_next_file(&err,
3551
 
                                                 fil_path_to_mysql_datadir,
3552
 
                                                 dir, &dbinfo);
3553
 
        }
3554
 
 
3555
 
        mem_free(dbpath);
3556
 
 
3557
 
        if (0 != os_file_closedir(dir)) {
3558
 
                fprintf(stderr,
3559
 
                        "InnoDB: Error: could not close MySQL datadir\n");
3560
 
 
3561
 
                return(DB_ERROR);
3562
 
        }
3563
 
 
3564
 
        return(err);
3565
 
}
3566
 
 
3567
 
/*******************************************************************//**
3568
 
Returns TRUE if a single-table tablespace does not exist in the memory cache,
3569
 
or is being deleted there.
3570
 
@return TRUE if does not exist or is being\ deleted */
3571
 
UNIV_INTERN
3572
 
ibool
3573
 
fil_tablespace_deleted_or_being_deleted_in_mem(
3574
 
/*===========================================*/
3575
 
        ulint           id,     /*!< in: space id */
3576
 
        ib_int64_t      version)/*!< in: tablespace_version should be this; if
3577
 
                                you pass -1 as the value of this, then this
3578
 
                                parameter is ignored */
3579
 
{
3580
 
        fil_space_t*    space;
3581
 
 
3582
 
        ut_ad(fil_system);
3583
 
 
3584
 
        mutex_enter(&fil_system->mutex);
3585
 
 
3586
 
        space = fil_space_get_by_id(id);
3587
 
 
3588
 
        if (space == NULL || space->is_being_deleted) {
3589
 
                mutex_exit(&fil_system->mutex);
3590
 
 
3591
 
                return(TRUE);
3592
 
        }
3593
 
 
3594
 
        if (version != ((ib_int64_t)-1)
3595
 
            && space->tablespace_version != version) {
3596
 
                mutex_exit(&fil_system->mutex);
3597
 
 
3598
 
                return(TRUE);
3599
 
        }
3600
 
 
3601
 
        mutex_exit(&fil_system->mutex);
3602
 
 
3603
 
        return(FALSE);
3604
 
}
3605
 
 
3606
 
/*******************************************************************//**
3607
 
Returns TRUE if a single-table tablespace exists in the memory cache.
3608
 
@return TRUE if exists */
3609
 
UNIV_INTERN
3610
 
ibool
3611
 
fil_tablespace_exists_in_mem(
3612
 
/*=========================*/
3613
 
        ulint   id)     /*!< in: space id */
3614
 
{
3615
 
        fil_space_t*    space;
3616
 
 
3617
 
        ut_ad(fil_system);
3618
 
 
3619
 
        mutex_enter(&fil_system->mutex);
3620
 
 
3621
 
        space = fil_space_get_by_id(id);
3622
 
 
3623
 
        mutex_exit(&fil_system->mutex);
3624
 
 
3625
 
        return(space != NULL);
3626
 
}
3627
 
 
3628
 
/*******************************************************************//**
3629
 
Returns TRUE if a matching tablespace exists in the InnoDB tablespace memory
3630
 
cache. Note that if we have not done a crash recovery at the database startup,
3631
 
there may be many tablespaces which are not yet in the memory cache.
3632
 
@return TRUE if a matching tablespace exists in the memory cache */
3633
 
UNIV_INTERN
3634
 
ibool
3635
 
fil_space_for_table_exists_in_mem(
3636
 
/*==============================*/
3637
 
        ulint           id,             /*!< in: space id */
3638
 
        const char*     name,           /*!< in: table name in the standard
3639
 
                                        'databasename/tablename' format or
3640
 
                                        the dir path to a temp table */
3641
 
        ibool           is_temp,        /*!< in: TRUE if created with CREATE
3642
 
                                        TEMPORARY TABLE */
3643
 
        ibool           mark_space,     /*!< in: in crash recovery, at database
3644
 
                                        startup we mark all spaces which have
3645
 
                                        an associated table in the InnoDB
3646
 
                                        data dictionary, so that
3647
 
                                        we can print a warning about orphaned
3648
 
                                        tablespaces */
3649
 
        ibool           print_error_if_does_not_exist)
3650
 
                                        /*!< in: print detailed error
3651
 
                                        information to the .err log if a
3652
 
                                        matching tablespace is not found from
3653
 
                                        memory */
3654
 
{
3655
 
        fil_space_t*    namespace;
3656
 
        fil_space_t*    space;
3657
 
        char*           path;
3658
 
 
3659
 
        ut_ad(fil_system);
3660
 
 
3661
 
        mutex_enter(&fil_system->mutex);
3662
 
 
3663
 
        path = fil_make_ibd_name(name, is_temp);
3664
 
 
3665
 
        /* Look if there is a space with the same id */
3666
 
 
3667
 
        space = fil_space_get_by_id(id);
3668
 
 
3669
 
        /* Look if there is a space with the same name; the name is the
3670
 
        directory path from the datadir to the file */
3671
 
 
3672
 
        namespace = fil_space_get_by_name(path);
3673
 
        if (space && space == namespace) {
3674
 
                /* Found */
3675
 
 
3676
 
                if (mark_space) {
3677
 
                        space->mark = TRUE;
3678
 
                }
3679
 
 
3680
 
                mem_free(path);
3681
 
                mutex_exit(&fil_system->mutex);
3682
 
 
3683
 
                return(TRUE);
3684
 
        }
3685
 
 
3686
 
        if (!print_error_if_does_not_exist) {
3687
 
 
3688
 
                mem_free(path);
3689
 
                mutex_exit(&fil_system->mutex);
3690
 
 
3691
 
                return(FALSE);
3692
 
        }
3693
 
 
3694
 
        if (space == NULL) {
3695
 
                if (namespace == NULL) {
3696
 
                        ut_print_timestamp(stderr);
3697
 
                        fputs("  InnoDB: Error: table ", stderr);
3698
 
                        ut_print_filename(stderr, name);
3699
 
                        fprintf(stderr, "\n"
3700
 
                                "InnoDB: in InnoDB data dictionary"
3701
 
                                " has tablespace id %lu,\n"
3702
 
                                "InnoDB: but tablespace with that id"
3703
 
                                " or name does not exist. Have\n"
3704
 
                                "InnoDB: you deleted or moved .ibd files?\n"
3705
 
                                "InnoDB: This may also be a table created with"
3706
 
                                " CREATE TEMPORARY TABLE\n"
3707
 
                                "InnoDB: whose .ibd and .frm files"
3708
 
                                " MySQL automatically removed, but the\n"
3709
 
                                "InnoDB: table still exists in the"
3710
 
                                " InnoDB internal data dictionary.\n",
3711
 
                                (ulong) id);
3712
 
                } else {
3713
 
                        ut_print_timestamp(stderr);
3714
 
                        fputs("  InnoDB: Error: table ", stderr);
3715
 
                        ut_print_filename(stderr, name);
3716
 
                        fprintf(stderr, "\n"
3717
 
                                "InnoDB: in InnoDB data dictionary has"
3718
 
                                " tablespace id %lu,\n"
3719
 
                                "InnoDB: but a tablespace with that id"
3720
 
                                " does not exist. There is\n"
3721
 
                                "InnoDB: a tablespace of name %s and id %lu,"
3722
 
                                " though. Have\n"
3723
 
                                "InnoDB: you deleted or moved .ibd files?\n",
3724
 
                                (ulong) id, namespace->name,
3725
 
                                (ulong) namespace->id);
3726
 
                }
3727
 
error_exit:
3728
 
                fputs("InnoDB: Please refer to\n"
3729
 
                      "InnoDB: " REFMAN "innodb-troubleshooting-datadict.html\n"
3730
 
                      "InnoDB: for how to resolve the issue.\n", stderr);
3731
 
 
3732
 
                mem_free(path);
3733
 
                mutex_exit(&fil_system->mutex);
3734
 
 
3735
 
                return(FALSE);
3736
 
        }
3737
 
 
3738
 
        if (0 != strcmp(space->name, path)) {
3739
 
                ut_print_timestamp(stderr);
3740
 
                fputs("  InnoDB: Error: table ", stderr);
3741
 
                ut_print_filename(stderr, name);
3742
 
                fprintf(stderr, "\n"
3743
 
                        "InnoDB: in InnoDB data dictionary has"
3744
 
                        " tablespace id %lu,\n"
3745
 
                        "InnoDB: but the tablespace with that id"
3746
 
                        " has name %s.\n"
3747
 
                        "InnoDB: Have you deleted or moved .ibd files?\n",
3748
 
                        (ulong) id, space->name);
3749
 
 
3750
 
                if (namespace != NULL) {
3751
 
                        fputs("InnoDB: There is a tablespace"
3752
 
                              " with the right name\n"
3753
 
                              "InnoDB: ", stderr);
3754
 
                        ut_print_filename(stderr, namespace->name);
3755
 
                        fprintf(stderr, ", but its id is %lu.\n",
3756
 
                                (ulong) namespace->id);
3757
 
                }
3758
 
 
3759
 
                goto error_exit;
3760
 
        }
3761
 
 
3762
 
        mem_free(path);
3763
 
        mutex_exit(&fil_system->mutex);
3764
 
 
3765
 
        return(FALSE);
3766
 
}
3767
 
 
3768
 
/*******************************************************************//**
3769
 
Checks if a single-table tablespace for a given table name exists in the
3770
 
tablespace memory cache.
3771
 
@return space id, ULINT_UNDEFINED if not found */
3772
 
static
3773
 
ulint
3774
 
fil_get_space_id_for_table(
3775
 
/*=======================*/
3776
 
        const char*     name)   /*!< in: table name in the standard
3777
 
                                'databasename/tablename' format */
3778
 
{
3779
 
        fil_space_t*    namespace;
3780
 
        ulint           id              = ULINT_UNDEFINED;
3781
 
        char*           path;
3782
 
 
3783
 
        ut_ad(fil_system);
3784
 
 
3785
 
        mutex_enter(&fil_system->mutex);
3786
 
 
3787
 
        path = fil_make_ibd_name(name, FALSE);
3788
 
 
3789
 
        /* Look if there is a space with the same name; the name is the
3790
 
        directory path to the file */
3791
 
 
3792
 
        namespace = fil_space_get_by_name(path);
3793
 
 
3794
 
        if (namespace) {
3795
 
                id = namespace->id;
3796
 
        }
3797
 
 
3798
 
        mem_free(path);
3799
 
 
3800
 
        mutex_exit(&fil_system->mutex);
3801
 
 
3802
 
        return(id);
3803
 
}
3804
 
 
3805
 
/**********************************************************************//**
3806
 
Tries to extend a data file so that it would accommodate the number of pages
3807
 
given. The tablespace must be cached in the memory cache. If the space is big
3808
 
enough already, does nothing.
3809
 
@return TRUE if success */
3810
 
UNIV_INTERN
3811
 
ibool
3812
 
fil_extend_space_to_desired_size(
3813
 
/*=============================*/
3814
 
        ulint*  actual_size,    /*!< out: size of the space after extension;
3815
 
                                if we ran out of disk space this may be lower
3816
 
                                than the desired size */
3817
 
        ulint   space_id,       /*!< in: space id */
3818
 
        ulint   size_after_extend)/*!< in: desired size in pages after the
3819
 
                                extension; if the current space size is bigger
3820
 
                                than this already, the function does nothing */
3821
 
{
3822
 
        fil_node_t*     node;
3823
 
        fil_space_t*    space;
3824
 
        byte*           buf2;
3825
 
        byte*           buf;
3826
 
        ulint           buf_size;
3827
 
        ulint           start_page_no;
3828
 
        ulint           file_start_page_no;
3829
 
        ulint           offset_high;
3830
 
        ulint           offset_low;
3831
 
        ulint           page_size;
3832
 
        ibool           success         = TRUE;
3833
 
 
3834
 
        fil_mutex_enter_and_prepare_for_io(space_id);
3835
 
 
3836
 
        space = fil_space_get_by_id(space_id);
3837
 
        ut_a(space);
3838
 
 
3839
 
        if (space->size >= size_after_extend) {
3840
 
                /* Space already big enough */
3841
 
 
3842
 
                *actual_size = space->size;
3843
 
 
3844
 
                mutex_exit(&fil_system->mutex);
3845
 
 
3846
 
                return(TRUE);
3847
 
        }
3848
 
 
3849
 
        page_size = dict_table_flags_to_zip_size(space->flags);
3850
 
        if (!page_size) {
3851
 
                page_size = UNIV_PAGE_SIZE;
3852
 
        }
3853
 
 
3854
 
        node = UT_LIST_GET_LAST(space->chain);
3855
 
 
3856
 
        fil_node_prepare_for_io(node, fil_system, space);
3857
 
 
3858
 
        start_page_no = space->size;
3859
 
        file_start_page_no = space->size - node->size;
3860
 
 
3861
 
        /* Extend at most 64 pages at a time */
3862
 
        buf_size = ut_min(64, size_after_extend - start_page_no) * page_size;
3863
 
        buf2 = mem_alloc(buf_size + page_size);
3864
 
        buf = ut_align(buf2, page_size);
3865
 
 
3866
 
        memset(buf, 0, buf_size);
3867
 
 
3868
 
        while (start_page_no < size_after_extend) {
3869
 
                ulint   n_pages = ut_min(buf_size / page_size,
3870
 
                                         size_after_extend - start_page_no);
3871
 
 
3872
 
                offset_high = (start_page_no - file_start_page_no)
3873
 
                        / (4096 * ((1024 * 1024) / page_size));
3874
 
                offset_low  = ((start_page_no - file_start_page_no)
3875
 
                               % (4096 * ((1024 * 1024) / page_size)))
3876
 
                        * page_size;
3877
 
#ifdef UNIV_HOTBACKUP
3878
 
                success = os_file_write(node->name, node->handle, buf,
3879
 
                                        offset_low, offset_high,
3880
 
                                        page_size * n_pages);
3881
 
#else
3882
 
                success = os_aio(OS_FILE_WRITE, OS_AIO_SYNC,
3883
 
                                 node->name, node->handle, buf,
3884
 
                                 offset_low, offset_high,
3885
 
                                 page_size * n_pages,
3886
 
                                 NULL, NULL);
3887
 
#endif
3888
 
                if (success) {
3889
 
                        node->size += n_pages;
3890
 
                        space->size += n_pages;
3891
 
 
3892
 
                        os_has_said_disk_full = FALSE;
3893
 
                } else {
3894
 
                        /* Let us measure the size of the file to determine
3895
 
                        how much we were able to extend it */
3896
 
 
3897
 
                        n_pages = ((ulint)
3898
 
                                   (os_file_get_size_as_iblonglong(
3899
 
                                           node->handle)
3900
 
                                    / page_size)) - node->size;
3901
 
 
3902
 
                        node->size += n_pages;
3903
 
                        space->size += n_pages;
3904
 
 
3905
 
                        break;
3906
 
                }
3907
 
 
3908
 
                start_page_no += n_pages;
3909
 
        }
3910
 
 
3911
 
        mem_free(buf2);
3912
 
 
3913
 
        fil_node_complete_io(node, fil_system, OS_FILE_WRITE);
3914
 
 
3915
 
        *actual_size = space->size;
3916
 
 
3917
 
#ifndef UNIV_HOTBACKUP
3918
 
        if (space_id == 0) {
3919
 
                ulint pages_per_mb = (1024 * 1024) / page_size;
3920
 
 
3921
 
                /* Keep the last data file size info up to date, rounded to
3922
 
                full megabytes */
3923
 
 
3924
 
                srv_data_file_sizes[srv_n_data_files - 1]
3925
 
                        = (node->size / pages_per_mb) * pages_per_mb;
3926
 
        }
3927
 
#endif /* !UNIV_HOTBACKUP */
3928
 
 
3929
 
        /*
3930
 
        printf("Extended %s to %lu, actual size %lu pages\n", space->name,
3931
 
        size_after_extend, *actual_size); */
3932
 
        mutex_exit(&fil_system->mutex);
3933
 
 
3934
 
        fil_flush(space_id);
3935
 
 
3936
 
        return(success);
3937
 
}
3938
 
 
3939
 
#ifdef UNIV_HOTBACKUP
3940
 
/********************************************************************//**
3941
 
Extends all tablespaces to the size stored in the space header. During the
3942
 
ibbackup --apply-log phase we extended the spaces on-demand so that log records
3943
 
could be applied, but that may have left spaces still too small compared to
3944
 
the size stored in the space header. */
3945
 
UNIV_INTERN
3946
 
void
3947
 
fil_extend_tablespaces_to_stored_len(void)
3948
 
/*======================================*/
3949
 
{
3950
 
        fil_space_t*    space;
3951
 
        byte*           buf;
3952
 
        ulint           actual_size;
3953
 
        ulint           size_in_header;
3954
 
        ulint           error;
3955
 
        ibool           success;
3956
 
 
3957
 
        buf = mem_alloc(UNIV_PAGE_SIZE);
3958
 
 
3959
 
        mutex_enter(&fil_system->mutex);
3960
 
 
3961
 
        space = UT_LIST_GET_FIRST(fil_system->space_list);
3962
 
 
3963
 
        while (space) {
3964
 
                ut_a(space->purpose == FIL_TABLESPACE);
3965
 
 
3966
 
                mutex_exit(&fil_system->mutex); /* no need to protect with a
3967
 
                                              mutex, because this is a
3968
 
                                              single-threaded operation */
3969
 
                error = fil_read(TRUE, space->id,
3970
 
                                 dict_table_flags_to_zip_size(space->flags),
3971
 
                                 0, 0, UNIV_PAGE_SIZE, buf, NULL);
3972
 
                ut_a(error == DB_SUCCESS);
3973
 
 
3974
 
                size_in_header = fsp_get_size_low(buf);
3975
 
 
3976
 
                success = fil_extend_space_to_desired_size(
3977
 
                        &actual_size, space->id, size_in_header);
3978
 
                if (!success) {
3979
 
                        fprintf(stderr,
3980
 
                                "InnoDB: Error: could not extend the"
3981
 
                                " tablespace of %s\n"
3982
 
                                "InnoDB: to the size stored in header,"
3983
 
                                " %lu pages;\n"
3984
 
                                "InnoDB: size after extension %lu pages\n"
3985
 
                                "InnoDB: Check that you have free disk space"
3986
 
                                " and retry!\n",
3987
 
                                space->name, size_in_header, actual_size);
3988
 
                        exit(1);
3989
 
                }
3990
 
 
3991
 
                mutex_enter(&fil_system->mutex);
3992
 
 
3993
 
                space = UT_LIST_GET_NEXT(space_list, space);
3994
 
        }
3995
 
 
3996
 
        mutex_exit(&fil_system->mutex);
3997
 
 
3998
 
        mem_free(buf);
3999
 
}
4000
 
#endif
4001
 
 
4002
 
/*========== RESERVE FREE EXTENTS (for a B-tree split, for example) ===*/
4003
 
 
4004
 
/*******************************************************************//**
4005
 
Tries to reserve free extents in a file space.
4006
 
@return TRUE if succeed */
4007
 
UNIV_INTERN
4008
 
ibool
4009
 
fil_space_reserve_free_extents(
4010
 
/*===========================*/
4011
 
        ulint   id,             /*!< in: space id */
4012
 
        ulint   n_free_now,     /*!< in: number of free extents now */
4013
 
        ulint   n_to_reserve)   /*!< in: how many one wants to reserve */
4014
 
{
4015
 
        fil_space_t*    space;
4016
 
        ibool           success;
4017
 
 
4018
 
        ut_ad(fil_system);
4019
 
 
4020
 
        mutex_enter(&fil_system->mutex);
4021
 
 
4022
 
        space = fil_space_get_by_id(id);
4023
 
 
4024
 
        ut_a(space);
4025
 
 
4026
 
        if (space->n_reserved_extents + n_to_reserve > n_free_now) {
4027
 
                success = FALSE;
4028
 
        } else {
4029
 
                space->n_reserved_extents += n_to_reserve;
4030
 
                success = TRUE;
4031
 
        }
4032
 
 
4033
 
        mutex_exit(&fil_system->mutex);
4034
 
 
4035
 
        return(success);
4036
 
}
4037
 
 
4038
 
/*******************************************************************//**
4039
 
Releases free extents in a file space. */
4040
 
UNIV_INTERN
4041
 
void
4042
 
fil_space_release_free_extents(
4043
 
/*===========================*/
4044
 
        ulint   id,             /*!< in: space id */
4045
 
        ulint   n_reserved)     /*!< in: how many one reserved */
4046
 
{
4047
 
        fil_space_t*    space;
4048
 
 
4049
 
        ut_ad(fil_system);
4050
 
 
4051
 
        mutex_enter(&fil_system->mutex);
4052
 
 
4053
 
        space = fil_space_get_by_id(id);
4054
 
 
4055
 
        ut_a(space);
4056
 
        ut_a(space->n_reserved_extents >= n_reserved);
4057
 
 
4058
 
        space->n_reserved_extents -= n_reserved;
4059
 
 
4060
 
        mutex_exit(&fil_system->mutex);
4061
 
}
4062
 
 
4063
 
/*******************************************************************//**
4064
 
Gets the number of reserved extents. If the database is silent, this number
4065
 
should be zero. */
4066
 
UNIV_INTERN
4067
 
ulint
4068
 
fil_space_get_n_reserved_extents(
4069
 
/*=============================*/
4070
 
        ulint   id)             /*!< in: space id */
4071
 
{
4072
 
        fil_space_t*    space;
4073
 
        ulint           n;
4074
 
 
4075
 
        ut_ad(fil_system);
4076
 
 
4077
 
        mutex_enter(&fil_system->mutex);
4078
 
 
4079
 
        space = fil_space_get_by_id(id);
4080
 
 
4081
 
        ut_a(space);
4082
 
 
4083
 
        n = space->n_reserved_extents;
4084
 
 
4085
 
        mutex_exit(&fil_system->mutex);
4086
 
 
4087
 
        return(n);
4088
 
}
4089
 
 
4090
 
/*============================ FILE I/O ================================*/
4091
 
 
4092
 
/********************************************************************//**
4093
 
NOTE: you must call fil_mutex_enter_and_prepare_for_io() first!
4094
 
 
4095
 
Prepares a file node for i/o. Opens the file if it is closed. Updates the
4096
 
pending i/o's field in the node and the system appropriately. Takes the node
4097
 
off the LRU list if it is in the LRU list. The caller must hold the fil_sys
4098
 
mutex. */
4099
 
static
4100
 
void
4101
 
fil_node_prepare_for_io(
4102
 
/*====================*/
4103
 
        fil_node_t*     node,   /*!< in: file node */
4104
 
        fil_system_t*   system, /*!< in: tablespace memory cache */
4105
 
        fil_space_t*    space)  /*!< in: space */
4106
 
{
4107
 
        ut_ad(node && system && space);
4108
 
        ut_ad(mutex_own(&(system->mutex)));
4109
 
 
4110
 
        if (system->n_open > system->max_n_open + 5) {
4111
 
                ut_print_timestamp(stderr);
4112
 
                fprintf(stderr,
4113
 
                        "  InnoDB: Warning: open files %lu"
4114
 
                        " exceeds the limit %lu\n",
4115
 
                        (ulong) system->n_open,
4116
 
                        (ulong) system->max_n_open);
4117
 
        }
4118
 
 
4119
 
        if (node->open == FALSE) {
4120
 
                /* File is closed: open it */
4121
 
                ut_a(node->n_pending == 0);
4122
 
 
4123
 
                fil_node_open_file(node, system, space);
4124
 
        }
4125
 
 
4126
 
        if (node->n_pending == 0 && space->purpose == FIL_TABLESPACE
4127
 
            && space->id != 0) {
4128
 
                /* The node is in the LRU list, remove it */
4129
 
 
4130
 
                ut_a(UT_LIST_GET_LEN(system->LRU) > 0);
4131
 
 
4132
 
                UT_LIST_REMOVE(LRU, system->LRU, node);
4133
 
        }
4134
 
 
4135
 
        node->n_pending++;
4136
 
}
4137
 
 
4138
 
/********************************************************************//**
4139
 
Updates the data structures when an i/o operation finishes. Updates the
4140
 
pending i/o's field in the node appropriately. */
4141
 
static
4142
 
void
4143
 
fil_node_complete_io(
4144
 
/*=================*/
4145
 
        fil_node_t*     node,   /*!< in: file node */
4146
 
        fil_system_t*   system, /*!< in: tablespace memory cache */
4147
 
        ulint           type)   /*!< in: OS_FILE_WRITE or OS_FILE_READ; marks
4148
 
                                the node as modified if
4149
 
                                type == OS_FILE_WRITE */
4150
 
{
4151
 
        ut_ad(node);
4152
 
        ut_ad(system);
4153
 
        ut_ad(mutex_own(&(system->mutex)));
4154
 
 
4155
 
        ut_a(node->n_pending > 0);
4156
 
 
4157
 
        node->n_pending--;
4158
 
 
4159
 
        if (type == OS_FILE_WRITE) {
4160
 
                system->modification_counter++;
4161
 
                node->modification_counter = system->modification_counter;
4162
 
 
4163
 
                if (!node->space->is_in_unflushed_spaces) {
4164
 
 
4165
 
                        node->space->is_in_unflushed_spaces = TRUE;
4166
 
                        UT_LIST_ADD_FIRST(unflushed_spaces,
4167
 
                                          system->unflushed_spaces,
4168
 
                                          node->space);
4169
 
                }
4170
 
        }
4171
 
 
4172
 
        if (node->n_pending == 0 && node->space->purpose == FIL_TABLESPACE
4173
 
            && node->space->id != 0) {
4174
 
                /* The node must be put back to the LRU list */
4175
 
                UT_LIST_ADD_FIRST(LRU, system->LRU, node);
4176
 
        }
4177
 
}
4178
 
 
4179
 
/********************************************************************//**
4180
 
Report information about an invalid page access. */
4181
 
static
4182
 
void
4183
 
fil_report_invalid_page_access(
4184
 
/*===========================*/
4185
 
        ulint           block_offset,   /*!< in: block offset */
4186
 
        ulint           space_id,       /*!< in: space id */
4187
 
        const char*     space_name,     /*!< in: space name */
4188
 
        ulint           byte_offset,    /*!< in: byte offset */
4189
 
        ulint           len,            /*!< in: I/O length */
4190
 
        ulint           type)           /*!< in: I/O type */
4191
 
{
4192
 
        fprintf(stderr,
4193
 
                "InnoDB: Error: trying to access page number %lu"
4194
 
                " in space %lu,\n"
4195
 
                "InnoDB: space name %s,\n"
4196
 
                "InnoDB: which is outside the tablespace bounds.\n"
4197
 
                "InnoDB: Byte offset %lu, len %lu, i/o type %lu.\n"
4198
 
                "InnoDB: If you get this error at mysqld startup,"
4199
 
                " please check that\n"
4200
 
                "InnoDB: your my.cnf matches the ibdata files"
4201
 
                " that you have in the\n"
4202
 
                "InnoDB: MySQL server.\n",
4203
 
                (ulong) block_offset, (ulong) space_id, space_name,
4204
 
                (ulong) byte_offset, (ulong) len, (ulong) type);
4205
 
}
4206
 
 
4207
 
/********************************************************************//**
4208
 
Reads or writes data. This operation is asynchronous (aio).
4209
 
@return DB_SUCCESS, or DB_TABLESPACE_DELETED if we are trying to do
4210
 
i/o on a tablespace which does not exist */
4211
 
UNIV_INTERN
4212
 
ulint
4213
 
fil_io(
4214
 
/*===*/
4215
 
        ulint   type,           /*!< in: OS_FILE_READ or OS_FILE_WRITE,
4216
 
                                ORed to OS_FILE_LOG, if a log i/o
4217
 
                                and ORed to OS_AIO_SIMULATED_WAKE_LATER
4218
 
                                if simulated aio and we want to post a
4219
 
                                batch of i/os; NOTE that a simulated batch
4220
 
                                may introduce hidden chances of deadlocks,
4221
 
                                because i/os are not actually handled until
4222
 
                                all have been posted: use with great
4223
 
                                caution! */
4224
 
        ibool   sync,           /*!< in: TRUE if synchronous aio is desired */
4225
 
        ulint   space_id,       /*!< in: space id */
4226
 
        ulint   zip_size,       /*!< in: compressed page size in bytes;
4227
 
                                0 for uncompressed pages */
4228
 
        ulint   block_offset,   /*!< in: offset in number of blocks */
4229
 
        ulint   byte_offset,    /*!< in: remainder of offset in bytes; in
4230
 
                                aio this must be divisible by the OS block
4231
 
                                size */
4232
 
        ulint   len,            /*!< in: how many bytes to read or write; this
4233
 
                                must not cross a file boundary; in aio this
4234
 
                                must be a block size multiple */
4235
 
        void*   buf,            /*!< in/out: buffer where to store read data
4236
 
                                or from where to write; in aio this must be
4237
 
                                appropriately aligned */
4238
 
        void*   message)        /*!< in: message for aio handler if non-sync
4239
 
                                aio used, else ignored */
4240
 
{
4241
 
        ulint           mode;
4242
 
        fil_space_t*    space;
4243
 
        fil_node_t*     node;
4244
 
        ulint           offset_high;
4245
 
        ulint           offset_low;
4246
 
        ibool           ret;
4247
 
        ulint           is_log;
4248
 
        ulint           wake_later;
4249
 
 
4250
 
        is_log = type & OS_FILE_LOG;
4251
 
        type = type & ~OS_FILE_LOG;
4252
 
 
4253
 
        wake_later = type & OS_AIO_SIMULATED_WAKE_LATER;
4254
 
        type = type & ~OS_AIO_SIMULATED_WAKE_LATER;
4255
 
 
4256
 
        ut_ad(byte_offset < UNIV_PAGE_SIZE);
4257
 
        ut_ad(!zip_size || !byte_offset);
4258
 
        ut_ad(ut_is_2pow(zip_size));
4259
 
        ut_ad(buf);
4260
 
        ut_ad(len > 0);
4261
 
#if (1 << UNIV_PAGE_SIZE_SHIFT) != UNIV_PAGE_SIZE
4262
 
# error "(1 << UNIV_PAGE_SIZE_SHIFT) != UNIV_PAGE_SIZE"
4263
 
#endif
4264
 
        ut_ad(fil_validate());
4265
 
#ifndef UNIV_HOTBACKUP
4266
 
# ifndef UNIV_LOG_DEBUG
4267
 
        /* ibuf bitmap pages must be read in the sync aio mode: */
4268
 
        ut_ad(recv_no_ibuf_operations || (type == OS_FILE_WRITE)
4269
 
              || !ibuf_bitmap_page(zip_size, block_offset)
4270
 
              || sync || is_log);
4271
 
        ut_ad(!ibuf_inside() || is_log || (type == OS_FILE_WRITE)
4272
 
              || ibuf_page(space_id, zip_size, block_offset, NULL));
4273
 
# endif /* UNIV_LOG_DEBUG */
4274
 
        if (sync) {
4275
 
                mode = OS_AIO_SYNC;
4276
 
        } else if (is_log) {
4277
 
                mode = OS_AIO_LOG;
4278
 
        } else if (type == OS_FILE_READ
4279
 
                   && !recv_no_ibuf_operations
4280
 
                   && ibuf_page(space_id, zip_size, block_offset, NULL)) {
4281
 
                mode = OS_AIO_IBUF;
4282
 
        } else {
4283
 
                mode = OS_AIO_NORMAL;
4284
 
        }
4285
 
#else /* !UNIV_HOTBACKUP */
4286
 
        ut_a(sync);
4287
 
        mode = OS_AIO_SYNC;
4288
 
#endif /* !UNIV_HOTBACKUP */
4289
 
 
4290
 
        if (type == OS_FILE_READ) {
4291
 
                srv_data_read+= len;
4292
 
        } else if (type == OS_FILE_WRITE) {
4293
 
                srv_data_written+= len;
4294
 
        }
4295
 
 
4296
 
        /* Reserve the fil_system mutex and make sure that we can open at
4297
 
        least one file while holding it, if the file is not already open */
4298
 
 
4299
 
        fil_mutex_enter_and_prepare_for_io(space_id);
4300
 
 
4301
 
        space = fil_space_get_by_id(space_id);
4302
 
 
4303
 
        if (!space) {
4304
 
                mutex_exit(&fil_system->mutex);
4305
 
 
4306
 
                ut_print_timestamp(stderr);
4307
 
                fprintf(stderr,
4308
 
                        "  InnoDB: Error: trying to do i/o"
4309
 
                        " to a tablespace which does not exist.\n"
4310
 
                        "InnoDB: i/o type %lu, space id %lu,"
4311
 
                        " page no. %lu, i/o length %lu bytes\n",
4312
 
                        (ulong) type, (ulong) space_id, (ulong) block_offset,
4313
 
                        (ulong) len);
4314
 
 
4315
 
                return(DB_TABLESPACE_DELETED);
4316
 
        }
4317
 
 
4318
 
        ut_ad((mode != OS_AIO_IBUF) || (space->purpose == FIL_TABLESPACE));
4319
 
 
4320
 
        node = UT_LIST_GET_FIRST(space->chain);
4321
 
 
4322
 
        for (;;) {
4323
 
                if (UNIV_UNLIKELY(node == NULL)) {
4324
 
                        fil_report_invalid_page_access(
4325
 
                                block_offset, space_id, space->name,
4326
 
                                byte_offset, len, type);
4327
 
 
4328
 
                        ut_error;
4329
 
                }
4330
 
 
4331
 
                if (space->id != 0 && node->size == 0) {
4332
 
                        /* We do not know the size of a single-table tablespace
4333
 
                        before we open the file */
4334
 
 
4335
 
                        break;
4336
 
                }
4337
 
 
4338
 
                if (node->size > block_offset) {
4339
 
                        /* Found! */
4340
 
                        break;
4341
 
                } else {
4342
 
                        block_offset -= node->size;
4343
 
                        node = UT_LIST_GET_NEXT(chain, node);
4344
 
                }
4345
 
        }
4346
 
 
4347
 
        /* Open file if closed */
4348
 
        fil_node_prepare_for_io(node, fil_system, space);
4349
 
 
4350
 
        /* Check that at least the start offset is within the bounds of a
4351
 
        single-table tablespace */
4352
 
        if (UNIV_UNLIKELY(node->size <= block_offset)
4353
 
            && space->id != 0 && space->purpose == FIL_TABLESPACE) {
4354
 
 
4355
 
                fil_report_invalid_page_access(
4356
 
                        block_offset, space_id, space->name, byte_offset,
4357
 
                        len, type);
4358
 
 
4359
 
                ut_error;
4360
 
        }
4361
 
 
4362
 
        /* Now we have made the changes in the data structures of fil_system */
4363
 
        mutex_exit(&fil_system->mutex);
4364
 
 
4365
 
        /* Calculate the low 32 bits and the high 32 bits of the file offset */
4366
 
 
4367
 
        if (!zip_size) {
4368
 
                offset_high = (block_offset >> (32 - UNIV_PAGE_SIZE_SHIFT));
4369
 
                offset_low  = ((block_offset << UNIV_PAGE_SIZE_SHIFT)
4370
 
                               & 0xFFFFFFFFUL) + byte_offset;
4371
 
 
4372
 
                ut_a(node->size - block_offset
4373
 
                     >= ((byte_offset + len + (UNIV_PAGE_SIZE - 1))
4374
 
                         / UNIV_PAGE_SIZE));
4375
 
        } else {
4376
 
                ulint   zip_size_shift;
4377
 
                switch (zip_size) {
4378
 
                case 1024: zip_size_shift = 10; break;
4379
 
                case 2048: zip_size_shift = 11; break;
4380
 
                case 4096: zip_size_shift = 12; break;
4381
 
                case 8192: zip_size_shift = 13; break;
4382
 
                case 16384: zip_size_shift = 14; break;
4383
 
                default: ut_error;
4384
 
                }
4385
 
                offset_high = block_offset >> (32 - zip_size_shift);
4386
 
                offset_low = (block_offset << zip_size_shift & 0xFFFFFFFFUL)
4387
 
                        + byte_offset;
4388
 
                ut_a(node->size - block_offset
4389
 
                     >= (len + (zip_size - 1)) / zip_size);
4390
 
        }
4391
 
 
4392
 
        /* Do aio */
4393
 
 
4394
 
        ut_a(byte_offset % OS_FILE_LOG_BLOCK_SIZE == 0);
4395
 
        ut_a((len % OS_FILE_LOG_BLOCK_SIZE) == 0);
4396
 
 
4397
 
#ifdef UNIV_HOTBACKUP
4398
 
        /* In ibbackup do normal i/o, not aio */
4399
 
        if (type == OS_FILE_READ) {
4400
 
                ret = os_file_read(node->handle, buf, offset_low, offset_high,
4401
 
                                   len);
4402
 
        } else {
4403
 
                ret = os_file_write(node->name, node->handle, buf,
4404
 
                                    offset_low, offset_high, len);
4405
 
        }
4406
 
#else
4407
 
        /* Queue the aio request */
4408
 
        ret = os_aio(type, mode | wake_later, node->name, node->handle, buf,
4409
 
                     offset_low, offset_high, len, node, message);
4410
 
#endif
4411
 
        ut_a(ret);
4412
 
 
4413
 
        if (mode == OS_AIO_SYNC) {
4414
 
                /* The i/o operation is already completed when we return from
4415
 
                os_aio: */
4416
 
 
4417
 
                mutex_enter(&fil_system->mutex);
4418
 
 
4419
 
                fil_node_complete_io(node, fil_system, type);
4420
 
 
4421
 
                mutex_exit(&fil_system->mutex);
4422
 
 
4423
 
                ut_ad(fil_validate());
4424
 
        }
4425
 
 
4426
 
        return(DB_SUCCESS);
4427
 
}
4428
 
 
4429
 
#ifndef UNIV_HOTBACKUP
4430
 
/**********************************************************************//**
4431
 
Waits for an aio operation to complete. This function is used to write the
4432
 
handler for completed requests. The aio array of pending requests is divided
4433
 
into segments (see os0file.c for more info). The thread specifies which
4434
 
segment it wants to wait for. */
4435
 
UNIV_INTERN
4436
 
void
4437
 
fil_aio_wait(
4438
 
/*=========*/
4439
 
        ulint   segment)        /*!< in: the number of the segment in the aio
4440
 
                                array to wait for */
4441
 
{
4442
 
        ibool           ret;
4443
 
        fil_node_t*     fil_node;
4444
 
        void*           message;
4445
 
        ulint           type;
4446
 
 
4447
 
        ut_ad(fil_validate());
4448
 
 
4449
 
        if (srv_use_native_aio) {
4450
 
                srv_set_io_thread_op_info(segment, "native aio handle");
4451
 
#ifdef WIN_ASYNC_IO
4452
 
                ret = os_aio_windows_handle(segment, 0, &fil_node,
4453
 
                                            &message, &type);
4454
 
#elif defined(LINUX_NATIVE_AIO)
4455
 
                ret = os_aio_linux_handle(segment, &fil_node,
4456
 
                                          &message, &type);
4457
 
#else
4458
 
                ret = 0; /* Eliminate compiler warning */
4459
 
                ut_error;
4460
 
#endif
4461
 
        } else {
4462
 
                srv_set_io_thread_op_info(segment, "simulated aio handle");
4463
 
 
4464
 
                ret = os_aio_simulated_handle(segment, &fil_node,
4465
 
                                              &message, &type);
4466
 
        }
4467
 
 
4468
 
        ut_a(ret);
4469
 
 
4470
 
        srv_set_io_thread_op_info(segment, "complete io for fil node");
4471
 
 
4472
 
        mutex_enter(&fil_system->mutex);
4473
 
 
4474
 
        fil_node_complete_io(fil_node, fil_system, type);
4475
 
 
4476
 
        mutex_exit(&fil_system->mutex);
4477
 
 
4478
 
        ut_ad(fil_validate());
4479
 
 
4480
 
        /* Do the i/o handling */
4481
 
        /* IMPORTANT: since i/o handling for reads will read also the insert
4482
 
        buffer in tablespace 0, you have to be very careful not to introduce
4483
 
        deadlocks in the i/o system. We keep tablespace 0 data files always
4484
 
        open, and use a special i/o thread to serve insert buffer requests. */
4485
 
 
4486
 
        if (fil_node->space->purpose == FIL_TABLESPACE) {
4487
 
                srv_set_io_thread_op_info(segment, "complete io for buf page");
4488
 
                buf_page_io_complete(message);
4489
 
        } else {
4490
 
                srv_set_io_thread_op_info(segment, "complete io for log");
4491
 
                log_io_complete(message);
4492
 
        }
4493
 
}
4494
 
#endif /* UNIV_HOTBACKUP */
4495
 
 
4496
 
/**********************************************************************//**
4497
 
Flushes to disk possible writes cached by the OS. If the space does not exist
4498
 
or is being dropped, does not do anything. */
4499
 
UNIV_INTERN
4500
 
void
4501
 
fil_flush(
4502
 
/*======*/
4503
 
        ulint   space_id)       /*!< in: file space id (this can be a group of
4504
 
                                log files or a tablespace of the database) */
4505
 
{
4506
 
        fil_space_t*    space;
4507
 
        fil_node_t*     node;
4508
 
        os_file_t       file;
4509
 
        ib_int64_t      old_mod_counter;
4510
 
 
4511
 
        mutex_enter(&fil_system->mutex);
4512
 
 
4513
 
        space = fil_space_get_by_id(space_id);
4514
 
 
4515
 
        if (!space || space->is_being_deleted) {
4516
 
                mutex_exit(&fil_system->mutex);
4517
 
 
4518
 
                return;
4519
 
        }
4520
 
 
4521
 
        space->n_pending_flushes++;     /*!< prevent dropping of the space while
4522
 
                                        we are flushing */
4523
 
        node = UT_LIST_GET_FIRST(space->chain);
4524
 
 
4525
 
        while (node) {
4526
 
                if (node->modification_counter > node->flush_counter) {
4527
 
                        ut_a(node->open);
4528
 
 
4529
 
                        /* We want to flush the changes at least up to
4530
 
                        old_mod_counter */
4531
 
                        old_mod_counter = node->modification_counter;
4532
 
 
4533
 
                        if (space->purpose == FIL_TABLESPACE) {
4534
 
                                fil_n_pending_tablespace_flushes++;
4535
 
                        } else {
4536
 
                                fil_n_pending_log_flushes++;
4537
 
                                fil_n_log_flushes++;
4538
 
                        }
4539
 
#ifdef __WIN__
4540
 
                        if (node->is_raw_disk) {
4541
 
 
4542
 
                                goto skip_flush;
4543
 
                        }
4544
 
#endif
4545
 
retry:
4546
 
                        if (node->n_pending_flushes > 0) {
4547
 
                                /* We want to avoid calling os_file_flush() on
4548
 
                                the file twice at the same time, because we do
4549
 
                                not know what bugs OS's may contain in file
4550
 
                                i/o; sleep for a while */
4551
 
 
4552
 
                                mutex_exit(&fil_system->mutex);
4553
 
 
4554
 
                                os_thread_sleep(20000);
4555
 
 
4556
 
                                mutex_enter(&fil_system->mutex);
4557
 
 
4558
 
                                if (node->flush_counter >= old_mod_counter) {
4559
 
 
4560
 
                                        goto skip_flush;
4561
 
                                }
4562
 
 
4563
 
                                goto retry;
4564
 
                        }
4565
 
 
4566
 
                        ut_a(node->open);
4567
 
                        file = node->handle;
4568
 
                        node->n_pending_flushes++;
4569
 
 
4570
 
                        mutex_exit(&fil_system->mutex);
4571
 
 
4572
 
                        /* fprintf(stderr, "Flushing to file %s\n",
4573
 
                        node->name); */
4574
 
 
4575
 
                        os_file_flush(file);
4576
 
 
4577
 
                        mutex_enter(&fil_system->mutex);
4578
 
 
4579
 
                        node->n_pending_flushes--;
4580
 
skip_flush:
4581
 
                        if (node->flush_counter < old_mod_counter) {
4582
 
                                node->flush_counter = old_mod_counter;
4583
 
 
4584
 
                                if (space->is_in_unflushed_spaces
4585
 
                                    && fil_space_is_flushed(space)) {
4586
 
 
4587
 
                                        space->is_in_unflushed_spaces = FALSE;
4588
 
 
4589
 
                                        UT_LIST_REMOVE(
4590
 
                                                unflushed_spaces,
4591
 
                                                fil_system->unflushed_spaces,
4592
 
                                                space);
4593
 
                                }
4594
 
                        }
4595
 
 
4596
 
                        if (space->purpose == FIL_TABLESPACE) {
4597
 
                                fil_n_pending_tablespace_flushes--;
4598
 
                        } else {
4599
 
                                fil_n_pending_log_flushes--;
4600
 
                        }
4601
 
                }
4602
 
 
4603
 
                node = UT_LIST_GET_NEXT(chain, node);
4604
 
        }
4605
 
 
4606
 
        space->n_pending_flushes--;
4607
 
 
4608
 
        mutex_exit(&fil_system->mutex);
4609
 
}
4610
 
 
4611
 
/**********************************************************************//**
4612
 
Flushes to disk the writes in file spaces of the given type possibly cached by
4613
 
the OS. */
4614
 
UNIV_INTERN
4615
 
void
4616
 
fil_flush_file_spaces(
4617
 
/*==================*/
4618
 
        ulint   purpose)        /*!< in: FIL_TABLESPACE, FIL_LOG */
4619
 
{
4620
 
        fil_space_t*    space;
4621
 
        ulint*          space_ids;
4622
 
        ulint           n_space_ids;
4623
 
        ulint           i;
4624
 
 
4625
 
        mutex_enter(&fil_system->mutex);
4626
 
 
4627
 
        n_space_ids = UT_LIST_GET_LEN(fil_system->unflushed_spaces);
4628
 
        if (n_space_ids == 0) {
4629
 
 
4630
 
                mutex_exit(&fil_system->mutex);
4631
 
                return;
4632
 
        }
4633
 
 
4634
 
        /* Assemble a list of space ids to flush.  Previously, we
4635
 
        traversed fil_system->unflushed_spaces and called UT_LIST_GET_NEXT()
4636
 
        on a space that was just removed from the list by fil_flush().
4637
 
        Thus, the space could be dropped and the memory overwritten. */
4638
 
        space_ids = mem_alloc(n_space_ids * sizeof *space_ids);
4639
 
 
4640
 
        n_space_ids = 0;
4641
 
 
4642
 
        for (space = UT_LIST_GET_FIRST(fil_system->unflushed_spaces);
4643
 
             space;
4644
 
             space = UT_LIST_GET_NEXT(unflushed_spaces, space)) {
4645
 
 
4646
 
                if (space->purpose == purpose && !space->is_being_deleted) {
4647
 
 
4648
 
                        space_ids[n_space_ids++] = space->id;
4649
 
                }
4650
 
        }
4651
 
 
4652
 
        mutex_exit(&fil_system->mutex);
4653
 
 
4654
 
        /* Flush the spaces.  It will not hurt to call fil_flush() on
4655
 
        a non-existing space id. */
4656
 
        for (i = 0; i < n_space_ids; i++) {
4657
 
 
4658
 
                fil_flush(space_ids[i]);
4659
 
        }
4660
 
 
4661
 
        mem_free(space_ids);
4662
 
}
4663
 
 
4664
 
/******************************************************************//**
4665
 
Checks the consistency of the tablespace cache.
4666
 
@return TRUE if ok */
4667
 
UNIV_INTERN
4668
 
ibool
4669
 
fil_validate(void)
4670
 
/*==============*/
4671
 
{
4672
 
        fil_space_t*    space;
4673
 
        fil_node_t*     fil_node;
4674
 
        ulint           n_open          = 0;
4675
 
        ulint           i;
4676
 
 
4677
 
        mutex_enter(&fil_system->mutex);
4678
 
 
4679
 
        /* Look for spaces in the hash table */
4680
 
 
4681
 
        for (i = 0; i < hash_get_n_cells(fil_system->spaces); i++) {
4682
 
 
4683
 
                space = HASH_GET_FIRST(fil_system->spaces, i);
4684
 
 
4685
 
                while (space != NULL) {
4686
 
                        UT_LIST_VALIDATE(chain, fil_node_t, space->chain,
4687
 
                                         ut_a(ut_list_node_313->open
4688
 
                                              || !ut_list_node_313->n_pending));
4689
 
 
4690
 
                        fil_node = UT_LIST_GET_FIRST(space->chain);
4691
 
 
4692
 
                        while (fil_node != NULL) {
4693
 
                                if (fil_node->n_pending > 0) {
4694
 
                                        ut_a(fil_node->open);
4695
 
                                }
4696
 
 
4697
 
                                if (fil_node->open) {
4698
 
                                        n_open++;
4699
 
                                }
4700
 
                                fil_node = UT_LIST_GET_NEXT(chain, fil_node);
4701
 
                        }
4702
 
                        space = HASH_GET_NEXT(hash, space);
4703
 
                }
4704
 
        }
4705
 
 
4706
 
        ut_a(fil_system->n_open == n_open);
4707
 
 
4708
 
        UT_LIST_VALIDATE(LRU, fil_node_t, fil_system->LRU, (void) 0);
4709
 
 
4710
 
        fil_node = UT_LIST_GET_FIRST(fil_system->LRU);
4711
 
 
4712
 
        while (fil_node != NULL) {
4713
 
                ut_a(fil_node->n_pending == 0);
4714
 
                ut_a(fil_node->open);
4715
 
                ut_a(fil_node->space->purpose == FIL_TABLESPACE);
4716
 
                ut_a(fil_node->space->id != 0);
4717
 
 
4718
 
                fil_node = UT_LIST_GET_NEXT(LRU, fil_node);
4719
 
        }
4720
 
 
4721
 
        mutex_exit(&fil_system->mutex);
4722
 
 
4723
 
        return(TRUE);
4724
 
}
4725
 
 
4726
 
/********************************************************************//**
4727
 
Returns TRUE if file address is undefined.
4728
 
@return TRUE if undefined */
4729
 
UNIV_INTERN
4730
 
ibool
4731
 
fil_addr_is_null(
4732
 
/*=============*/
4733
 
        fil_addr_t      addr)   /*!< in: address */
4734
 
{
4735
 
        return(addr.page == FIL_NULL);
4736
 
}
4737
 
 
4738
 
/********************************************************************//**
4739
 
Get the predecessor of a file page.
4740
 
@return FIL_PAGE_PREV */
4741
 
UNIV_INTERN
4742
 
ulint
4743
 
fil_page_get_prev(
4744
 
/*==============*/
4745
 
        const byte*     page)   /*!< in: file page */
4746
 
{
4747
 
        return(mach_read_from_4(page + FIL_PAGE_PREV));
4748
 
}
4749
 
 
4750
 
/********************************************************************//**
4751
 
Get the successor of a file page.
4752
 
@return FIL_PAGE_NEXT */
4753
 
UNIV_INTERN
4754
 
ulint
4755
 
fil_page_get_next(
4756
 
/*==============*/
4757
 
        const byte*     page)   /*!< in: file page */
4758
 
{
4759
 
        return(mach_read_from_4(page + FIL_PAGE_NEXT));
4760
 
}
4761
 
 
4762
 
/*********************************************************************//**
4763
 
Sets the file page type. */
4764
 
UNIV_INTERN
4765
 
void
4766
 
fil_page_set_type(
4767
 
/*==============*/
4768
 
        byte*   page,   /*!< in/out: file page */
4769
 
        ulint   type)   /*!< in: type */
4770
 
{
4771
 
        ut_ad(page);
4772
 
 
4773
 
        mach_write_to_2(page + FIL_PAGE_TYPE, type);
4774
 
}
4775
 
 
4776
 
/*********************************************************************//**
4777
 
Gets the file page type.
4778
 
@return type; NOTE that if the type has not been written to page, the
4779
 
return value not defined */
4780
 
UNIV_INTERN
4781
 
ulint
4782
 
fil_page_get_type(
4783
 
/*==============*/
4784
 
        const byte*     page)   /*!< in: file page */
4785
 
{
4786
 
        ut_ad(page);
4787
 
 
4788
 
        return(mach_read_from_2(page + FIL_PAGE_TYPE));
4789
 
}
4790
 
 
4791
 
/********************************************************************
4792
 
Initializes the tablespace memory cache. */
4793
 
UNIV_INTERN
4794
 
void
4795
 
fil_close(void)
4796
 
/*===========*/
4797
 
{
4798
 
#ifndef UNIV_HOTBACKUP
4799
 
        /* The mutex should already have been freed. */
4800
 
        ut_ad(fil_system->mutex.magic_n == 0);
4801
 
#endif /* !UNIV_HOTBACKUP */
4802
 
 
4803
 
        hash_table_free(fil_system->spaces);
4804
 
 
4805
 
        hash_table_free(fil_system->name_hash);
4806
 
 
4807
 
        ut_a(UT_LIST_GET_LEN(fil_system->LRU) == 0);
4808
 
        ut_a(UT_LIST_GET_LEN(fil_system->unflushed_spaces) == 0);
4809
 
        ut_a(UT_LIST_GET_LEN(fil_system->space_list) == 0);
4810
 
 
4811
 
        mem_free(fil_system);
4812
 
 
4813
 
        fil_system = NULL;
4814
 
}