~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/innobase/buf/buf0lru.cc

  • Committer: Laurynas Biveinis
  • Date: 2011-04-07 12:10:16 UTC
  • mto: This revision was merged to the branch mainline in revision 2273.
  • Revision ID: laurynas.biveinis@percona.com-20110407121016-hvn63tw2yde6jepo
Port Percona's innodb_lru_dump_restore.patch

Show diffs side-by-side

added added

removed removed

Lines of Context:
2110
2110
        memset(&buf_LRU_stat_cur, 0, sizeof buf_LRU_stat_cur);
2111
2111
}
2112
2112
 
 
2113
/********************************************************************//**
 
2114
Dump the LRU page list to the specific file. */
 
2115
#define LRU_DUMP_FILE "ib_lru_dump"
 
2116
 
 
2117
UNIV_INTERN
 
2118
bool
 
2119
buf_LRU_file_dump(void)
 
2120
/*===================*/
 
2121
{
 
2122
        os_file_t       dump_file = -1;
 
2123
        ibool           success;
 
2124
        byte*           buffer_base = NULL;
 
2125
        byte*           buffer = NULL;
 
2126
        buf_page_t*     bpage;
 
2127
        ulint           buffers;
 
2128
        ulint           offset;
 
2129
        bool            ret = false;
 
2130
        ulint           i;
 
2131
 
 
2132
        for (i = 0; i < srv_n_data_files; i++) {
 
2133
                if (strstr(srv_data_file_names[i], LRU_DUMP_FILE) != NULL) {
 
2134
                        fprintf(stderr,
 
2135
                                " InnoDB: The name '%s' seems to be used for"
 
2136
                                " innodb_data_file_path. For safety, dumping of the LRU list"
 
2137
                                " is not being done.\n", LRU_DUMP_FILE);
 
2138
                        goto end;
 
2139
                }
 
2140
        }
 
2141
 
 
2142
        buffer_base = static_cast<byte *>(ut_malloc(2 * UNIV_PAGE_SIZE));
 
2143
        buffer = static_cast<byte *>(ut_align(buffer_base, UNIV_PAGE_SIZE));
 
2144
        if (buffer == NULL) {
 
2145
                fprintf(stderr,
 
2146
                        " InnoDB: cannot allocate buffer.\n");
 
2147
                goto end;
 
2148
        }
 
2149
 
 
2150
        dump_file = os_file_create(innodb_file_temp_key, LRU_DUMP_FILE, OS_FILE_OVERWRITE,
 
2151
                                   OS_FILE_NORMAL, OS_DATA_FILE, &success);
 
2152
        if (success == FALSE) {
 
2153
                os_file_get_last_error(TRUE);
 
2154
                fprintf(stderr,
 
2155
                        " InnoDB: cannot open %s\n", LRU_DUMP_FILE);
 
2156
                goto end;
 
2157
        }
 
2158
 
 
2159
        buffers = offset = 0;
 
2160
 
 
2161
        for (i = 0; i < srv_buf_pool_instances; i++) {
 
2162
                buf_pool_t*     buf_pool;
 
2163
 
 
2164
                buf_pool = buf_pool_from_array(i);
 
2165
 
 
2166
                buf_pool_mutex_enter(buf_pool);
 
2167
                bpage = UT_LIST_GET_LAST(buf_pool->LRU);
 
2168
 
 
2169
                while (bpage != NULL) {
 
2170
                        if (offset == 0) {
 
2171
                                memset(buffer, 0, UNIV_PAGE_SIZE);
 
2172
                        }
 
2173
 
 
2174
                        mach_write_to_4(buffer + offset * 4, bpage->space);
 
2175
                        offset++;
 
2176
                        mach_write_to_4(buffer + offset * 4, bpage->offset);
 
2177
                        offset++;
 
2178
 
 
2179
                        if (offset == UNIV_PAGE_SIZE/4) {
 
2180
                                success = os_file_write(LRU_DUMP_FILE, dump_file, buffer,
 
2181
                                                        (buffers << UNIV_PAGE_SIZE_SHIFT) & 0xFFFFFFFFUL,
 
2182
                                                        (buffers >> (32 - UNIV_PAGE_SIZE_SHIFT)),
 
2183
                                                        UNIV_PAGE_SIZE);
 
2184
                                if (success == FALSE) {
 
2185
                                        buf_pool_mutex_exit(buf_pool);
 
2186
                                        fprintf(stderr,
 
2187
                                                " InnoDB: cannot write page %lu of %s\n",
 
2188
                                                buffers, LRU_DUMP_FILE);
 
2189
                                        goto end;
 
2190
                                }
 
2191
                                buffers++;
 
2192
                                offset = 0;
 
2193
                        }
 
2194
 
 
2195
                        bpage = UT_LIST_GET_PREV(LRU, bpage);
 
2196
                }
 
2197
                buf_pool_mutex_exit(buf_pool);
 
2198
        }
 
2199
 
 
2200
        if (offset == 0) {
 
2201
                memset(buffer, 0, UNIV_PAGE_SIZE);
 
2202
        }
 
2203
 
 
2204
        mach_write_to_4(buffer + offset * 4, 0xFFFFFFFFUL);
 
2205
        offset++;
 
2206
        mach_write_to_4(buffer + offset * 4, 0xFFFFFFFFUL);
 
2207
        offset++;
 
2208
 
 
2209
        success = os_file_write(LRU_DUMP_FILE, dump_file, buffer,
 
2210
                                (buffers << UNIV_PAGE_SIZE_SHIFT) & 0xFFFFFFFFUL,
 
2211
                                (buffers >> (32 - UNIV_PAGE_SIZE_SHIFT)),
 
2212
                                UNIV_PAGE_SIZE);
 
2213
        if (success == FALSE) {
 
2214
                goto end;
 
2215
        }
 
2216
 
 
2217
        ret = true;
 
2218
end:
 
2219
        if (dump_file != -1)
 
2220
                os_file_close(dump_file);
 
2221
        if (buffer_base)
 
2222
                ut_free(buffer_base);
 
2223
 
 
2224
        return(ret);
 
2225
}
 
2226
 
 
2227
typedef struct {
 
2228
        ib_uint32_t space_id;
 
2229
        ib_uint32_t page_no;
 
2230
} dump_record_t;
 
2231
 
 
2232
static int dump_record_cmp(const void *a, const void *b)
 
2233
{
 
2234
        const dump_record_t *rec1 = (dump_record_t *) a;
 
2235
        const dump_record_t *rec2 = (dump_record_t *) b;
 
2236
 
 
2237
        if (rec1->space_id < rec2->space_id)
 
2238
                return -1;
 
2239
        if (rec1->space_id > rec2->space_id)
 
2240
                return 1;
 
2241
        if (rec1->page_no < rec2->page_no)
 
2242
                return -1;
 
2243
        return rec1->page_no > rec2->page_no;
 
2244
}
 
2245
 
 
2246
/********************************************************************//**
 
2247
Read the pages based on the specific file.*/
 
2248
UNIV_INTERN
 
2249
bool
 
2250
buf_LRU_file_restore(void)
 
2251
/*======================*/
 
2252
{
 
2253
        os_file_t       dump_file = -1;
 
2254
        ibool           success;
 
2255
        byte*           buffer_base = NULL;
 
2256
        byte*           buffer = NULL;
 
2257
        ulint           buffers;
 
2258
        ulint           offset;
 
2259
        ulint           reads = 0;
 
2260
        ulint           req = 0;
 
2261
        bool            terminated = false;
 
2262
        bool            ret = false;
 
2263
        dump_record_t*  records = NULL;
 
2264
        ulint           size;
 
2265
        ulint           size_high;
 
2266
        ulint           length;
 
2267
 
 
2268
        dump_file = os_file_create_simple_no_error_handling(innodb_file_temp_key,
 
2269
                                                            LRU_DUMP_FILE, OS_FILE_OPEN, OS_FILE_READ_ONLY, &success);
 
2270
        if (success == FALSE || !os_file_get_size(dump_file, &size, &size_high)) {
 
2271
                os_file_get_last_error(TRUE);
 
2272
                fprintf(stderr,
 
2273
                        " InnoDB: cannot open %s\n", LRU_DUMP_FILE);
 
2274
                goto end;
 
2275
        }
 
2276
        if (size == 0 || size_high > 0 || size % 8) {
 
2277
                fprintf(stderr, " InnoDB: broken LRU dump file\n");
 
2278
                goto end;
 
2279
        }
 
2280
        buffer_base = static_cast<byte *>(ut_malloc(2 * UNIV_PAGE_SIZE));
 
2281
        buffer = static_cast<byte *>(ut_align(buffer_base, UNIV_PAGE_SIZE));
 
2282
        records = static_cast<dump_record_t *>(ut_malloc(size));
 
2283
        if (buffer == NULL || records == NULL) {
 
2284
                fprintf(stderr,
 
2285
                        " InnoDB: cannot allocate buffer.\n");
 
2286
                goto end;
 
2287
        }
 
2288
 
 
2289
        buffers = 0;
 
2290
        length = 0;
 
2291
        while (!terminated) {
 
2292
                success = os_file_read(dump_file, buffer,
 
2293
                                       (buffers << UNIV_PAGE_SIZE_SHIFT) & 0xFFFFFFFFUL,
 
2294
                                       (buffers >> (32 - UNIV_PAGE_SIZE_SHIFT)),
 
2295
                                       UNIV_PAGE_SIZE);
 
2296
                if (success == FALSE) {
 
2297
                        fprintf(stderr,
 
2298
                                " InnoDB: either could not read page %lu of %s,"
 
2299
                                " or terminated unexpectedly.\n",
 
2300
                                buffers, LRU_DUMP_FILE);
 
2301
                        goto end;
 
2302
                }
 
2303
 
 
2304
                for (offset = 0; offset < UNIV_PAGE_SIZE/4; offset += 2) {
 
2305
                        ulint   space_id;
 
2306
                        ulint   page_no;
 
2307
 
 
2308
                        space_id = mach_read_from_4(buffer + offset * 4);
 
2309
                        page_no = mach_read_from_4(buffer + (offset + 1) * 4);
 
2310
                        if (space_id == 0xFFFFFFFFUL
 
2311
                            || page_no == 0xFFFFFFFFUL) {
 
2312
                                terminated = true;
 
2313
                                break;
 
2314
                        }
 
2315
 
 
2316
                        records[length].space_id = space_id;
 
2317
                        records[length].page_no = page_no;
 
2318
                        length++;
 
2319
                        if (length * 8 >= size) {
 
2320
                                fprintf(stderr,
 
2321
                                        " InnoDB: could not find the "
 
2322
                                        "end-of-file marker after reading "
 
2323
                                        "the expected %lu bytes from the "
 
2324
                                        "LRU dump file.\n"
 
2325
                                        " InnoDB: this could be caused by a "
 
2326
                                        "broken or incomplete file.\n"
 
2327
                                        " InnoDB: trying to process what has "
 
2328
                                        "been read so far.\n",
 
2329
                                        size);
 
2330
                                terminated = true;
 
2331
                                break;
 
2332
                        }
 
2333
                }
 
2334
                buffers++;
 
2335
        }
 
2336
 
 
2337
        qsort(records, length, sizeof(dump_record_t), dump_record_cmp);
 
2338
 
 
2339
        for (offset = 0; offset < length; offset++) {
 
2340
                ulint   space_id;
 
2341
                ulint   page_no;
 
2342
                ulint   zip_size;
 
2343
                ulint   err;
 
2344
                int64_t tablespace_version;
 
2345
 
 
2346
                space_id = records[offset].space_id;
 
2347
                page_no = records[offset].page_no;
 
2348
 
 
2349
                if (offset % 16 == 15) {
 
2350
                        os_aio_simulated_wake_handler_threads();
 
2351
                        buf_flush_free_margins();
 
2352
                }
 
2353
 
 
2354
                zip_size = fil_space_get_zip_size(space_id);
 
2355
                if (UNIV_UNLIKELY(zip_size == ULINT_UNDEFINED)) {
 
2356
                        continue;
 
2357
                }
 
2358
 
 
2359
                if (fil_is_exist(space_id, page_no)) {
 
2360
 
 
2361
                        tablespace_version = fil_space_get_version(space_id);
 
2362
 
 
2363
                        req++;
 
2364
                        reads += buf_read_page_low(&err, FALSE, BUF_READ_ANY_PAGE
 
2365
                                                   | OS_AIO_SIMULATED_WAKE_LATER,
 
2366
                                                   space_id, zip_size, TRUE,
 
2367
                                                   tablespace_version, page_no);
 
2368
                        buf_LRU_stat_inc_io();
 
2369
                }
 
2370
        }
 
2371
 
 
2372
        os_aio_simulated_wake_handler_threads();
 
2373
        buf_flush_free_margins();
 
2374
 
 
2375
        ut_print_timestamp(stderr);
 
2376
        fprintf(stderr,
 
2377
                " InnoDB: reading pages based on the dumped LRU list was done."
 
2378
                " (requested: %lu, read: %lu)\n", req, reads);
 
2379
        ret = true;
 
2380
end:
 
2381
        if (dump_file != -1)
 
2382
                os_file_close(dump_file);
 
2383
        if (buffer_base)
 
2384
                ut_free(buffer_base);
 
2385
        if (records)
 
2386
                ut_free(records);
 
2387
 
 
2388
        return(ret);
 
2389
}
 
2390
 
2113
2391
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
2114
2392
/**********************************************************************//**
2115
2393
Validates the LRU list for one buffer pool instance. */